Java processes remain alive after CRON - java

I created a jar that grabs an image from a URL (webcam of my favorite beach) and saves it to a file using the timestamp as a name. Yes, I know there are programs to do this - I'm a propellerhead and I wanted to do it myself. It works like a champ.
Then I scheduled it to run every minute with CRON. Again, worked like a champ.
* * * * * java -jar /apps/clearcapture.jar
After running for several hours (Mac OS 10.9) I found the machine running at a crawl. Activity Monitor revealed MANY java processes. Without counting them, I would guess that there was one instance for every time the image was captured.
So, what's going on here? I expect that when the jar is done, its parent Java instance would go away.
Thanks,
Chris

At the end of main method of the main class, you should call System.exit to explicitly exit the program. For better exception handling, you should capture all exceptions, log them into a proper log and call System.exit with system error output.

I resolved it by explicitly closing the HTTPUrlConnection at the conclusion of the download.

Related

WIX installer execute vbscript from CustomAction

I can't execute VBScript using WIX installer. Currently I have this part of WiX config:
<Binary Id='KillThatProcessBinary' SourceFile='KillThatProcess.vbs' />
<CustomAction Id="KillThatProcessAction"
Execute="immediate"
BinaryKey='KillThatProcessBinary'
VBScriptCall='KillThatProcessFunction'
Return="check"/>
<InstallExecuteSequence>
<Custom Action='KillThatProcessAction' Before='InstallValidate'/>
<ScheduleReboot After="InstallFinalize"/>
</InstallExecuteSequence>
And this VBS script (KillThatProcess.vbs):
Public Function KillThatProcessFunction()
Set oShell = WScript.CreateObject("WSCript.shell")
oShell.run "cmd /C wmic process where ""name like '%java%'"" delete"
Return 0
End Function
I already try to insert this script into CustomAction (as innerText), and add attribute: Script="vbscript". But nothing works, every time I got the error message - "There is a problem with this Windows Installer package. A script reqired for this install to complete could not be run. Contact your support personnel or package vendor."
And errors in log file:
Error 0x80070643: Failed to install MSI package.
[1A88:2FA4][2018-08-21T14:11:17]e000: Error 0x80070643: Failed to configure per-user MSI package.
[1A88:2FA4][2018-08-21T14:11:17]i319: Applied execute package: LPGateway, result: 0x80070643, restart: None
[1A88:2FA4][2018-08-21T14:11:17]e000: Error 0x80070643: Failed to execute MSI package.
I already execute this vbs script (not from installer) and it works. Anybody know what I do wrong?
There are a few issues I want to summarize:
VBA & VBScript Functions: That VBScript looks like it is actually VBA and calling VBScript in an MSI requires a bit of tweaking
to call VBScript functions properly.
Reboot: The reboot you schedule must get a better condition to avoid unexpected reboots.
Process Kill: What process are you trying to kill?
Elevation: If it is elevated you need to run the kill elevated for it to succeed. Your per-user setup is likely not set to
elevate at all (so you can generally only end processes running as yourself).
Restart Manager: Very often you do not need to kill processes, due to the Restart Manager feature of Windows that Windows
Installer tries to use. Attempt to explain this feature (look for
yellow sections).
Issue 1: That must be a VBA script and not a VBScript? For the record: I haven't seen return in VBScript? In VBScript you return from a function by setting the function name equal to whatever you want to return, quick sample:
result = IsEmptyString("")
MsgBox CStr(result)
Function IsEmptyString(str)
If str = "" Then
IsEmptyString = True
Else
IsEmptyString = False
End If
End Function
Note: The above is just a silly, rather meaningless example. For more elaborate checking try
IsBlank from ss64.com. VBScript comes with the functions IsEmpty and IsNull and IsObject.
When used in MSI files, I normally don't add a function in the VBScript, but just run the script directly, so running this VBScript should work:
MsgBox(Session.Property("ProductName"))
Inserting it into the WiX source (notice no function call specified):
<Binary Id='Sample.vbs' SourceFile='Sample.vbs' />
<CustomAction Id='Sample.vbs' VBScriptCall='' BinaryKey='Sample.vbs' Execute='immediate' Return='ignore'/>
Crucially your VBScript can still call other functions available in the same VBScript file. So in the above sample "IsEmptyString" can be called from the main "nameless" function at the top of the file.
Check Exit Code: And finally, any custom action set to check exit code can throw your setup into abort (immediate mode) or rollback (deferred mode). I would only check the exit code if you have to end the setup if the custom action can not run.
Issue 2: Reboots. This is a very serious issue in my opinion. I have seen people sent out the door for causing unexpected reboots during large scale deployments. Rebooting a knowledge worker's PC (and their managers) with a dozen Visual Studio windows open, dozens of browser windows and Word and Excel and you name it. It can cause a great deal of problems. And they may know where you live! :-)
Please read the following answer (at least its 3 bullet points at the beginning): Reboot on install, Don't reboot on uninstall
Issue 3: Process Kill. As indicated above the killing of processes is related to the reboot issues. It is not always necessary to kill processes if they are compliant with Windows Restart Manager as explained in the link above. Let me repeat it here (yellow sections should give you the gist of it - especially the second one I think).
There are a few different ways to kill processes. Note that the most common problem might be that you don't have the access rights and / or privileges to kill the process - no matter what tool or approach you use to do so.
Perhaps you can try the CloseApplication feature from the Util schema: http://wixtoolset.org/documentation/manual/v3/xsd/util/closeapplication.html
In Wix MSI: Killing a process upon uninstallation
Kill windows service forcefully in WIX (towards bottom)
Kill process using WMI / VBScript
Some people combine taskill.exe and WiX by means of the Quiet Execution Custom Action (CAQuietExec: hide command line windows). FireGiant documentation.
I am not sure which of these options to recommend. I don't like the concept of killing processes altogether, but sometimes there is no other option I guess.

Audio playback not working correctly

I'm developing a program that simply monitors a webpage for changes, and plays a sound file. I implemented similar to this answer using SwingUtilities.invokeLater and JOptionPane to make sure sound file is looped continuously.
Program works correctly. Now I would like to place it in crontab (on my Ubuntu Machine) and have it run every 30 minutes. That's where things stop working. I searched for why, and it looks like JOptionPane should be invoked from initial thread (which is the crontab process?). I understand that I just need to prevent main method from ending, but what would be the best approach (DataLine.Drain() ?).
You are trying to display something without making sure a display server is present and accessible (which is not a given for a process started by cron).
You can specify a display server by setting the DISPLAY variable to :0. For example:
* * * * * export DISPLAY=:0; YOUR_PROGRAM
See also https://stackoverflow.com/a/25182822/942774

How to close the javax application if the same instance is already running?

I am running my java application by jar file. Now a certain need forces me to check other instance of same application running or not on same Machine. For e.g i must restrict to run only one instance of application to make run, close other application (if running on other tab on terminal). I have searched similar threats from here, but actually unable to figure out.
The easiest way to achieve this would be to create a lock-file when you start your application. When you start a second instance it can check for the existence of such a file and terminate if one is found. When you close the first instance it has to delete this file of course before it finally terminates.

restart java.exe from an applet

I have an applet packaged with a third part dll (from JTwain). My applet scans documents from the TWAIN compatible default printer. The applet fails on a paper jam and won't recover. The user navigates away from the page and the applet is destroyed. When returning to the page it fails again. Closing the browser (which kills java.exe process on the pc), and then returning to the page clears the problem and everything works.
I want to restart everything without requiring users to close down the browser. I've added a GUID query string to the URL's from which the applets resources are loaded - so I know nothing is being cached. I've checked in the windows task manager and there is no process created by the dll, it's all happening within the main java.exe process. I tried wrapping the scanning process in a thread so I could interrupt it in the stop or destroy methods (just in case the applets thread weren't stopped when the applet was destroyed), but that didn't work.
Any suggest would be greatly appreciated. Ideally I'd like some way to restart java when the applet unloads (but I doubt that's possible).
UPDATE
I've spent a couple of days trying to identify what causes the applet to fail. I still don't know :(
When the paper jam occurs something (not my code), is producing a couple of popups. The first alerts the user of the jam, and can be closed by clicking the OK button. The second says 'reading from device' and hangs. It cannot be close with the red, close window, icon in the top corner - I kill it from the task manager and windows asks to send a report regarding the 'non-responsive program'. I assume these popups are produced by the dll. And given that the second hangs, my assumption is that a thread started by the dll has hung while retaining a lock on some component of the TWAIN application. I get
com.asprise.util.jtwain.JTwainException: Failed to open the specified data source:
Source: TW-Brother MFC-9970CDW LAN Thrown
..when I try to access the scanner.
I'm at a bit of a loss as to how I can get more information. I'm testing my applet on a windows virtual pc (so as to use ie7), and don't have a method for step debugging in this environment. (And it's crashing on third party code for which I have no source anyway)
I see only two practical options here:
Use an API that handles paper jam without problems. Of course, that is easy to say (get robust API), harder to find.
Launch the app. free floating using Java Web Start. If it freezes up, the user can kill it and click the link for another instance in a new JVM. Or the applet might also call BasicService.showDocument(URLof.jnlp) if it can detect a problem with the DLL and is not itself frozen.
Of course, you should also report the bug to the ..Asprise(?) developers. The optimal solution would be to have the problem fixed at its source. Anything we do here is a 'workaround'.

Using an empty file to have one application instance

There's probably other ways of doing this but I'd like to use an empty file to have one instance of an application running at a given time. This would be done by creating the file when the application is launched and have other application instances exit as soon as they detect the file.
The trouble with this approach is that the file can remain if the application stops unexpectedly and a ShutDownhook is proving unreliable.
How would you go about making this work as intended?
Bind to a high numbered port but don't listen. Two programs can't bind to the same TCP port on the same machine. Very cross-platform but still somewhat of a kludge.
Create the file and keep it open with an exclusive lock (that is, don't pass FILE_SHARE_READ, etc). When the second instance starts up, it tries to open the file and if it fails it means the first is still running.
If the first crashes, then Windows will automatically close all file handles and so the second process will come along, see that the file is there but since it can open it then it knows the first has crashed (this technique could also be used for a special dialog, "I see the previous instance of this application crashes, would you like to restore your last session?" or something)
You could always wrap your Java program in another program (doesn't need to be complicated - could even be a shell script) that would detect abnormal exit and delete the file. e.g.
if(!`java MyProgram`){
rm lockFile
}
This may be a little much. But you can start a ServerSocket and bind to some arbitrary port that each application knows. If the port is available the application wins to start up, if not a binding exception is thrown and the application gracefully stops.
There is probably a better way to do this than using a file but with that approach you could write a timestamp to the file and update it at regular intervals using a Timer. Then when your program starts it could compare the timestamp in the file with the current time and quit if it is too close. This guarantees that your program will be able to restart no matter how it was terminated.
Assuming the lock will be released when the application exits and deleting the file on startup does the trick. See the link below.
http://jimlife.wordpress.com/2008/07/21/java-application-make-sure-only-singleone-instance-running-with-file-lock-ampampampampamp-shutdownhook/
P.S: I've tried using delete when the application exits but it seems to fail.

Categories

Resources