single instance

Discussion in 'Java' started by Roedy Green, Jan 1, 2013.

  1. Roedy Green

    Roedy Green Guest

    What is the best way to ensure only a single instance of a Java
    program is running.

    I have used indicator files, but they can get screwed up if the user
    kills the program without going through the standard shutdown.

    Ideally, net new instance would just join the one already running.
    This is pure GUI, so I am not worried about adding new command line
    parms.
    --
    Roedy Green Canadian Mind Products http://mindprod.com
    Students who hire or con others to do their homework are as foolish
    as couch potatoes who hire others to go to the gym for them.
     
    Roedy Green, Jan 1, 2013
    #1
    1. Advertising

  2. Roedy Green

    Arne Vajhøj Guest

    On 1/1/2013 3:23 PM, Roedy Green wrote:
    > What is the best way to ensure only a single instance of a Java
    > program is running.
    >
    > I have used indicator files, but they can get screwed up if the user
    > kills the program without going through the standard shutdown.


    1) Some platform specific native code invoked via JNI.

    2) A file and if found the app prompts the user to abort or continue.

    3) Using IP port.

    > Ideally, net new instance would just join the one already running.


    ????

    Arne
     
    Arne Vajhøj, Jan 1, 2013
    #2
    1. Advertising

  3. Arne Vajhøj wrote:

    > On 1/1/2013 3:23 PM, Roedy Green wrote:
    >> What is the best way to ensure only a single instance of a Java
    >> program is running.
    >>
    >> I have used indicator files, but they can get screwed up if the user
    >> kills the program without going through the standard shutdown.

    >
    > 1) Some platform specific native code invoked via JNI.
    >
    > 2) A file and if found the app prompts the user to abort or continue.
    >
    > 3) Using IP port.


    Ok, so first, if you're doing a JWS app, you might want to try this:
    http://pscode.org/jws/api.html#sis and do as specified.

    Now if that's not the case then I'd go for a combination of #2 and #3. You
    can't catch all the failure modes, but you can at least eliminate the "user
    loves kill -9" threat.

    On launch of the first instance, your program could pick a random (high)
    port and open a socket. It then writes the port number to a temporary file
    at a known location.

    So now, on launch, all you have to do is check for the existance of that
    file. If it's not there, you start as normal, see above. If it is, you
    read the port number from the file, and try to connect to that socket. If
    you succeed, you assume the program's already running and whine to the user.
    If you fail, you assume the program was killed prematurely, you nuke the
    temp file, and proceed as normal.

    Of course that doesn't cover the case where your program gets whacked and
    something else starts listening on it in the meantime. You can work around
    that by having your program identify itself via said socket. It also
    doesn't handle the case where somebody deletes the temporary file while the
    app is running. Still, I suppose it's at least something of a decent
    platform-specific way of ensuring you're not allowing multiple instances of
    your program.

    All that said, I'd just use the typical pid file approach and assume that if
    the user decides to nuke the process they get to clean up the mess.

    -Rob
     
    Robert Tomsick, Jan 3, 2013
    #3
  4. Roedy Green

    Roedy Green Guest

    On Tue, 01 Jan 2013 12:23:45 -0800, Roedy Green
    <> wrote, quoted or indirectly quoted
    someone who said :

    >What is the best way to ensure only a single instance of a Java
    >program is running.


    I was expecting this to be a method in some obscure corner of the Java
    API. I was bracing myself for the usual RTFM (read all docs end to
    end and miss nothing).

    The only technique that does not have some major drawback is the UDP
    broadcast, but I don't fully understand it yet.

    I have recorded your ideas in my essay at
    http://mindprod.com/jgloss/singleinstance.html
    --
    Roedy Green Canadian Mind Products http://mindprod.com
    Students who hire or con others to do their homework are as foolish
    as couch potatoes who hire others to go to the gym for them.
     
    Roedy Green, Jan 3, 2013
    #4
  5. On 1/3/2013 12:55 AM, Peter Duniho wrote:
    > As far as the sockets approach goes, you might be able to avoid the need of
    > dealing with a magic file or hard-coded socket port by using UDP multicast
    > with the SO_REUSEADDR option. This would allow your program to join to a
    > multicast port without interference from other programs, ensuring it's
    > ready to receive a UDP datagram sent on the channel from a new instance
    > searching for a prior existing instance.
    >
    > Unfortunately, unlike the exclusive-create option available for a file,
    > there's no such built-in support for resolving race conditions in the
    > socket-based approach. Unless you are willing to go without a solution, or
    > are confident you can correctly design and implement a solution, you may
    > want to stick with the more user-driven approaches suggested.
    >
    > But it's there in case you want to try. :)
    >
    > Pete


    I'm not sure how you could do this without establishing what group and
    port your were going to use before hand. But maybe that isn't what you
    were saying.

    So what do you think of this implementation? I did try to start two
    copies with a batch file and I could get them to fail on occasion. I
    don't think it would be possible for a user to start two copies
    simultaneously though.

    Thanks,

    knute...

    import java.awt.*;
    import java.io.*;
    import java.lang.reflect.*;
    import java.net.*;
    import java.nio.charset.*;
    import java.util.*;
    import javax.swing.*;

    public class Exclusive implements Runnable {
    private final long myTime;
    private final MulticastSocket socket;
    private final InetAddress group;
    private final int port;

    private volatile boolean runFlag;
    private volatile Thread thread;

    public Exclusive(String ipStr, String portStr) throws IOException {
    myTime = System.currentTimeMillis();

    group = InetAddress.getByName(ipStr);
    port = Integer.parseInt(portStr);

    socket = new MulticastSocket(port);
    socket.joinGroup(group);
    }

    public void start() throws IOException {
    if (thread == null || !thread.isAlive()) {
    runFlag = true;
    thread = new Thread(this);
    thread.start();

    // send out my time
    String str = Long.toString(myTime);
    byte[] buf = str.getBytes(StandardCharsets.US_ASCII);
    DatagramPacket dp =
    new DatagramPacket(buf,buf.length,group,port);
    socket.send(dp);
    }
    }

    @Override public void run() {
    while (runFlag) {
    try {
    // receive their time
    byte[] buf = new byte[64];
    DatagramPacket dp = new DatagramPacket(buf,buf.length);
    socket.receive(dp);
    String timeStr = new String(dp.getData(),dp.getOffset(),
    dp.getLength(),StandardCharsets.US_ASCII);
    long theirTime = Long.parseLong(timeStr);
    // if we are seeing our own packet, do nothing
    if (theirTime == myTime) {
    // if their time is before my time, we need to shut down
    } else if (theirTime < myTime) {
    stop();
    shutdownHook();
    // if their time is after my time, send out my time
    } else if (theirTime > myTime) {
    String str = Long.toString(myTime);
    buf = str.getBytes(StandardCharsets.US_ASCII);
    dp = new DatagramPacket(buf,buf.length,group,port);
    socket.send(dp);
    }
    } catch (IOException|NumberFormatException ex) {
    ex.printStackTrace();
    stop();
    }
    }
    }

    private void stop() {
    if (thread != null && thread.isAlive()) {
    runFlag = false;
    if (socket != null)
    socket.close();
    }

    // signal the waitFor() method to stop waiting
    synchronized (this) {
    notify();
    }
    }

    // wait for two seconds to delay program startup until we have
    // time to determine if there is another copy running.
    // returns true if no other copy is running.
    public synchronized boolean waitFor() throws InterruptedException {
    wait(2000);

    return runFlag;
    }

    public void shutdownHook() {
    // can't use invokeLater()
    try {
    EventQueue.invokeAndWait(new Runnable() {
    public void run() {
    JOptionPane.showMessageDialog(null,
    "Another Copy of this Program is Already Running",
    "Start Inhibited",JOptionPane.ERROR_MESSAGE);
    }
    });
    } catch (InterruptedException|InvocationTargetException ex) {
    ex.printStackTrace();
    }
    }

    public static void main(String[] args) {
    try {
    Exclusive e = new Exclusive("227.228.229.230","23222");
    e.start();
    if (e.waitFor())
    System.out.println("no other copy running!");
    else
    System.out.println("another copy is running");

    } catch (IOException|InterruptedException ex) {
    // probably don't want to start if you get an exception either
    ex.printStackTrace();
    }
    }
    }

    --

    Knute Johnson
     
    Knute Johnson, Jan 4, 2013
    #5
  6. On Thu, 3 Jan 2013 19:56:37 -0800, Peter Duniho wrote:

    > On Thu, 03 Jan 2013 19:31:37 -0800, Knute Johnson wrote:
    >
    >> [...]
    >> So what do you think of this implementation? I did try to start two
    >> copies with a batch file and I could get them to fail on occasion. I
    >> don't think it would be possible for a user to start two copies
    >> simultaneously though.

    >
    > Oh, and it should go without saying that in a real implementation, each
    > program would have a way to include a unique identifier (i.e. similar to
    > the name one would use for a named mutex on Windows) in the transmitted
    > message, to insure against two completely different programs that are using
    > the same "exclusive" implementation from conflicting with each other.
    >
    > But I'll say it anyway. :)


    Why not just use the process PID as unique identifier?

    > It is important to keep in mind that even this approach is not 100%
    > reliable. UDP messages are not guaranteed delivery,


    This is loopback interface we're talking about, not the wild wild internet.

    In any event, the error message that was proposed isn't a very useful way
    of handling the situation. I'd suggest that once the old and new instance
    are in communication and agree on which is which:

    - The new instance sends the old its invocation command-line, then quietly
    terminates.
    - The old interprets this command-line and e.g. opens named documents in
    additional document windows. If those are JFrames the last one should
    automatically wind up with window focus.
    - If those are JInternalFrames, or there were no new documents to open, the
    old instance's main/most recently active JFrame grabs window focus.

    So, if you just double-click on the program somewhere, the existing
    instance jumps to the front of the window stack. If you double-click on a
    document associated with the program, it opens in the existing instance.
    This pattern of behavior is common in native apps that don't like running
    in multiple instances, and so replicating it would be best given the
    principle of least astonishment.

    Wagging a naughty-finger in the user's face because they double-clicked a
    document file associated with an already-open application, on the other
    hand, and forcing them to instead drag and drop it into the existing
    instance (or, worse, switch to the existing instance to use its File Open
    menu and re-browse the directory tree) would violate the same principle.

    --
    Hexapodia is the key insight.
     
    Twirlip of the Mists, Jan 4, 2013
    #6
  7. Roedy Green

    Daniel Pitts Guest

    On 1/1/13 12:23 PM, Roedy Green wrote:
    > What is the best way to ensure only a single instance of a Java
    > program is running.
    >
    > I have used indicator files, but they can get screwed up if the user
    > kills the program without going through the standard shutdown.
    >
    > Ideally, net new instance would just join the one already running.
    > This is pure GUI, so I am not worried about adding new command line
    > parms.
    >

    A common approach I've seen is to use an indicator file, which contains
    the PID of the main process. That way you can check if that PID is
    still active. This of course isn't platform independent. You could
    combine the idea with others in this thread though. Check the file,
    which contains a TCP port number, connect to that port number to check
    if the process is still alive.

    Just a thought.

    I might also have my program "watch" that file, and if it disappears or
    becomes modified, then shut down because I know the user is trying
    something they shouldn't.
     
    Daniel Pitts, Jan 4, 2013
    #7
  8. On Fri, 4 Jan 2013 10:22:44 -0800, Peter Duniho wrote:

    > On Fri, 4 Jan 2013 12:18:59 -0500, Twirlip of the Mists wrote:
    >
    >> Why not just use the process PID as unique identifier?

    >
    > You misunderstand.


    I do not.

    > The "unique identifier" is not per-process, but rather per-program.


    Then you should have just said so. Use argument 0 of the command line then
    -- that should be the path of the executable. Then each install of the
    application will be single-instance, but by making more than one install
    the user could have multiple instances. These instances would have separate
    sets of settings files, however, being from separate installs, so one of
    the two big reasons for inhibiting multi-instances doesn't apply there.
    (The other is user convenience -- opening a load of documents and having
    them all open in the same containing window, with maybe special drag and
    drop options available between them, and without as much memory use as if
    each had a separate process. If the user deliberately chooses to circumvent
    this for some reason, though, one should defer to the user's wishes having
    provided a reasonable default for the common case of a single install.)

    > Even if I was talking about a unique per-process identifier, process ID
    > isn't really all that great, because getting the process ID requires
    > platform-specific code.


    1. Getting argument 0 doesn't, which is what now seems like the best idea.
    2. Isn't there a Process class in the Java API as of a few versions ago
    that interacts with the host's job control?

    > Not as complicated as using platform-specific code
    > for the whole implementation (e.g. named mutex on Windows), but still not
    > platform-agnostic.


    The concept of a PID is platform-agnostic -- all Unices seem to have it,
    MacOS is a Unix nowadays, and newer Windowses have PIDs. It'd be surprising
    if there isn't a platform-agnostic way to get at PIDs -- a POSIX call that
    Windows supports, most likely.

    >>> It is important to keep in mind that even this approach is not 100%
    >>> reliable. UDP messages are not guaranteed delivery,

    >>
    >> This is loopback interface we're talking about, not the wild wild internet.

    >
    > Maybe you should have kept reading, [rest deleted unread]


    You will need to be more polite and less judgmental if you want me to read
    more of what you have to say. You catch more flies with honey than you do
    with vinegar, and repeatedly insinuating that I did various things wrong or
    should have done X instead of Y or etc. constitutes vinegar. Especially
    when done before a live studio audience.

    --
    Hexapodia is the key insight.
     
    Twirlip of the Mists, Jan 4, 2013
    #8
  9. On Fri, 04 Jan 2013 10:26:01 -0800, Daniel Pitts wrote:

    > I might also have my program "watch" that file, and if it disappears or
    > becomes modified, then shut down because I know the user is trying
    > something they shouldn't.


    I'm HIGHLY dubious of nannying your users to that extent. Unless it's very
    dangerous, in some sense, to allow multi-instances (data-destroying race
    conditions in important files in the install directory?), if the user takes
    specific and knowledgeable action to circumvent the default behavior of
    only having a single instance, the user should probably be deferred to and
    the perceived problem solved in other ways (e.g. using a lightweight but
    properly ACID database instead of just a file, or locking the file and
    requiring separate concurrent instances use separate files or even distinct
    installs altogether).

    I know that if I deliberately circumvent something like that, I do so at my
    own risk and buggy, even data-destroying behavior is theoretically possible
    among the consequences (so I should either not do so or back up the
    program's data files first).

    I also know that there have been many occasions when I've been frustrated
    by a program "straight-jacketing" me into being unable to do something the
    programmer thought unwise or even just unnecessary, but where the
    programmer clearly hadn't anticipated all the uses to which the program
    might be put, especially by someone that's a hacker and not just a garden
    variety end-user.

    Programs are the user's tools and, as such, should empower, not limit, the
    user. Whereas it can make plenty of sense to include safety features
    designed to make it difficult for the user to accidentally shoot himself in
    the foot, cut off his finger in the saw, or shoot his co-worker from across
    the room with the nailgun, it is rarely if ever worthwhile to additionally
    try to design in a "cop-in-the-box" intended to catch and "punish"
    deliberate attempts to circumvent such features. If I purposely circumvent
    the safety on a nailgun, I do so at my own risk and probably because a
    burglar broke into the shop and I need a makeshift weapon for self-defense
    in a hurry, rather than because I'm an irresponsible idiot, and if I *am*
    an irresponsible idiot, I'll probably find some other way to shoot myself
    or my co-worker no matter how idiot-proof you try to make the nailgun.

    Disclaiming all warranty and liability in the event of such tampering is
    the furthest it's generally reasonable to take matters -- and, of course,
    software makers are already in the habit of blanket disclaiming ALL
    liability, even for actual defects in workmanship!

    So I'd suggest that instead of monitoring the file for deletion or
    tampering you just name it something cutesy like "DELETING ME VOIDS
    WARRANTY AND MAY CAUSE MALFUNCTION.txt". :)

    Nah, probably not even that, since if the program hangs and has to be
    force-quit, then won't restart properly because of a stale lockfile, your
    support forums will end up chock full of long threads going

    Q: It hung, I end-tasked it, and it wont restart!
    A: Delete the lockfile and try restarting it again.
    Q: What's the "lockfile"?
    A: It's the file called "DELETING ME VOIDS WARRANTY..."
    Q: But I don't want to void my warranty and maybe cause even more bugs!
    A: The name's a joke. There's no warranty anyway and deleting it won't
    cause a malfunction if the program isn't currently running.
    Q: Are you sure?
    A: Yes.
    Q: Are you really, REALLY sure?
    A: Yes!
    Q: It won't void the warranty on my *computer itself* will it?
    A: It didn't come with the computer, so, no, it can't.
    Q: Hmm. It still doesn't seem like a good idea. I think I'll get a second
    opinion. <starts new thread on the same topic>
    A: <bangs head against wall>

    --
    Hexapodia is the key insight.
     
    Twirlip of the Mists, Jan 4, 2013
    #9
  10. On Fri, 4 Jan 2013 11:03:02 -0800, Peter Duniho wrote:

    > On Fri, 4 Jan 2013 13:44:56 -0500, Twirlip of the Mists wrote:
    >
    >> On Fri, 4 Jan 2013 10:22:44 -0800, Peter Duniho wrote:
    >>
    >>> You misunderstand.

    >>
    >> I do not.

    >
    > Not now, it appears. Clearly you did before.


    ....

    >> Then you should have just said so. [...]

    >
    > I did say so


    ....

    > Just because you incorrectly th[deleted]


    ....

    > You seem to have a log in your eye.[nuke]


    [plonk]

    ....

    --
    Hexapodia is the key insight.
     
    Twirlip of the Mists, Jan 4, 2013
    #10
  11. On Sat, 5 Jan 2013 17:43:15 +0000 (UTC), Martin Gregorie wrote:

    > On Sat, 05 Jan 2013 12:48:41 +0000, Chris Uppal wrote:
    >
    >> There may be something added to modern Linux (or whatever) that makes it
    >> easier to create shared temporary files (not the requirement here, of
    >> course). But there's nothing in "classic" *NIX (say from around the
    >> time of SysV).

    >
    > Correct: test C code written and checked to prove your point. The Stratus
    > VOS OS left the file in place: you could see it from list_directory after
    > it had been deleted, but Linux doesn't do that.
    >
    > However, the automatic cleanup is easy enough to manage from C via the
    > atexit() function, which is very to use since you just call atexit() near
    > the start of the main() function: once atexit() has registered your exit
    > action(s) you get on with whatever the program is meant to do in the
    > knowledge that these actions will happen regardless of how the program
    > exits (power failures and system crashes excluded).


    In other words, atexit is a fine way to implement this if you're happy with
    a solution that fails and leaves a stale lock every time there's a
    thunderstorm. :)

    > It looks as though the nearest we can come to this in Java is via
    > try...finally blocks.
    >
    > However, I'm wondering if the finally block would always execute, e.g. if
    > the try...finally block is in the main() method of a program that exits
    > leaving thread(s) running to do the work, does the finally block still
    > get still run when the last thread(s) terminates? I had a fairly cursory
    > look at JLS 14.20.1 but it wasn't clear on this point.


    The finally will execute when the main method exits, which, in a GUI
    program, is probably long *before* the app terminates. It won't execute at
    all in a console app that ends via System.exit(0) or similar without
    falling off the end of main. It will execute if it falls off the end of
    main however.

    Java has Runtime.getRuntime().addShutdownHook(Thread x), which *will* run
    on System.exit(0) and *won't* run immediately if the startup thread of a
    GUI app falls off the end of main.

    However, both a main finally block and addShutdownHook are vulnerable to
    the aforementioned thunderstorm, and, additionally, to all of the
    following:

    * VM crash
    * Crash (e.g. segfault) in native method
    * kill -9, force-quit, Task Manager End Task, and equivalents

    C's atexit is probably vulnerable to the latter two, mitigatable only
    partially by registering signal handlers.

    The only thing I can think of that even the thunderstorm won't **** up is
    an active system where the lockfile is only considered valid if some
    associated "heartbeat" is still going, so, the lockfile invalidates on a
    deadman switch even if not deleted. An associated pulse you can test for on
    a loopback port was already suggested elsewhere in this thread. Having the
    lockfile contents be a representation of a time, updated by the live
    application every 1 second, and treated as invalid if it's stale by at
    least 5 seconds, is another possibility -- a fresh instance can simply
    overwrite the file and carry on if it's older than 5 seconds, and otherwise
    wait (5 - file's age at time of startup-attempt) seconds to see if the file
    changes, then do whatever's appropriate based on whether it did or not. (On
    Unix, at least, you can just "touch" the file to "heartbeat" and test its
    modification time to "take a pulse".)

    --
    Hexapodia is the key insight.
     
    Twirlip of the Mists, Jan 5, 2013
    #11
  12. On 1/5/2013 12:43 PM, Martin Gregorie wrote:
    > However, the automatic cleanup is easy enough to manage from C via the
    > atexit() function, which is very to use since you just call atexit() near
    > the start of the main() function: once atexit() has registered your exit
    > action(s) you get on with whatever the program is meant to do in the
    > knowledge that these actions will happen regardless of how the program
    > exits (power failures and system crashes excluded).


    Unfortunately those may be a pretty big part of the actual
    problems encountered in the real world.

    We have been talking a lot about killing the process, but the
    above two seems much more likely to me.

    > It looks as though the nearest we can come to this in Java is via
    > try...finally blocks.


    To me Runtime addShutdownHook sounds closer in functionality.

    > However, I'm wondering if the finally block would always execute, e.g. if
    > the try...finally block is in the main() method of a program that exits
    > leaving thread(s) running to do the work, does the finally block still
    > get still run when the last thread(s) terminates? I had a fairly cursory
    > look at JLS 14.20.1 but it wasn't clear on this point.


    http://docs.oracle.com/javase/tutorial/essential/exceptions/finally.html

    says:

    Note: If the JVM exits while the try or catch code is being executed,
    then the finally block may not execute. Likewise, if the thread
    executing the try or catch code is interrupted or killed, the finally
    block may not execute even though the application as a whole continues.

    and:

    public class ExitFinally {
    public static void main(String[] args) {
    try {
    System.exit(0);
    } finally {
    System.out.println("final");
    }
    }
    }

    does not print anything.

    So I think the answer is NO.

    Arne
     
    Arne Vajhøj, Jan 6, 2013
    #12
  13. Roedy Green

    Arne Vajhøj Guest

    On 1/4/2013 1:44 PM, Twirlip of the Mists wrote:
    > On Fri, 4 Jan 2013 10:22:44 -0800, Peter Duniho wrote:
    >
    >> On Fri, 4 Jan 2013 12:18:59 -0500, Twirlip of the Mists wrote:
    >>
    >>> Why not just use the process PID as unique identifier?

    >>
    >> You misunderstand.

    >
    > I do not.


    Obviously you did.

    >> The "unique identifier" is not per-process, but rather per-program.

    >
    > Then you should have just said so.


    He did.

    <quote>
    Oh, and it should go without saying that in a real implementation, each
    program would have a way to include a unique identifier (i.e. similar to
    the name one would use for a named mutex on Windows) in the transmitted
    message, to insure against two completely different programs that are using
    the same "exclusive" implementation from conflicting with each
    other.</quote>

    "... each program would have a way to include a unique identifier ...
    to insure against two completely different programs ... conflicting
    with each other"

    Count the frequency of "program" and "process".

    >> Not as complicated as using platform-specific code
    >> for the whole implementation (e.g. named mutex on Windows), but still not
    >> platform-agnostic.

    >
    > The concept of a PID is platform-agnostic -- all Unices seem to have it,
    > MacOS is a Unix nowadays, and newer Windowses have PIDs. It'd be surprising
    > if there isn't a platform-agnostic way to get at PIDs -- a POSIX call that
    > Windows supports, most likely.


    *nix and Windows support does not mean platform-agnostic.

    >>>> It is important to keep in mind that even this approach is not 100%
    >>>> reliable. UDP messages are not guaranteed delivery,
    >>>
    >>> This is loopback interface we're talking about, not the wild wild internet.

    >>
    >> Maybe you should have kept reading, [rest deleted unread]

    >
    > You will need to be more polite and less judgmental if you want me to read
    > more of what you have to say.


    Peter most likely does not care whether you read his posts or not.

    Arne
     
    Arne Vajhøj, Jan 6, 2013
    #13
  14. Roedy Green

    Arne Vajhøj Guest

    On 1/4/2013 12:18 PM, Twirlip of the Mists wrote:
    > On Thu, 3 Jan 2013 19:56:37 -0800, Peter Duniho wrote:
    >> It is important to keep in mind that even this approach is not 100%
    >> reliable. UDP messages are not guaranteed delivery,

    >
    > This is loopback interface we're talking about, not the wild wild internet.


    Which does not contradict Peters statement.

    Arne
     
    Arne Vajhøj, Jan 6, 2013
    #14
  15. Roedy Green

    Roedy Green Guest

    On Sat, 5 Jan 2013 20:29:52 +0000 (UTC), Martin Gregorie
    <> wrote, quoted or indirectly quoted
    someone who said :

    >I don't think any of these approaches are immune to system crashes, but
    >should be good enough to prevent single processes, whether launched by a
    >user or automatically by the system, from running more copies that are
    >wanted.


    With windows perhaps you start a small service on every boot. When it
    starts, it can presume nothing is running. You could even interrogate
    at the command line it if is safe to start a new instance, rather than
    loading it and discovering only after it had started execution it
    should die..

    One feature of this system is you want it to check as early as
    possible in the load process if there is another instance.

    The other is a way of passing command line parms of a second instance
    to the first in some uniform way.

    It might be nice if the mechanism worked for code in any language.
    --
    Roedy Green Canadian Mind Products http://mindprod.com
    Students who hire or con others to do their homework are as foolish
    as couch potatoes who hire others to go to the gym for them.
     
    Roedy Green, Jan 6, 2013
    #15
  16. Roedy Green

    Arne Vajhøj Guest

    On 1/3/2013 10:12 AM, Roedy Green wrote:
    > On Tue, 01 Jan 2013 12:23:45 -0800, Roedy Green
    > <> wrote, quoted or indirectly quoted
    > someone who said :
    >> What is the best way to ensure only a single instance of a Java
    >> program is running.

    >
    > I was expecting this to be a method in some obscure corner of the Java
    > API. I was bracing myself for the usual RTFM (read all docs end to
    > end and miss nothing).
    >
    > The only technique that does not have some major drawback is the UDP
    > broadcast, but I don't fully understand it yet.
    >
    > I have recorded your ideas in my essay at
    > http://mindprod.com/jgloss/singleinstance.html


    <quote>
    Test for the presence of a busy.marker file. If one exists, abort. If
    not create one. The test and create can be in the bat file that triggers
    the app or in the app itself
    </quote>

    Who can see a concurrency problem in that logic?

    <quote>
    // if we are seeing our own packet, do nothing
    if ( theirTime == myTime )
    {
    </quote>

    Who can see a concurrency problem in that logic?

    <quote>
    public void shutdownHook()
    {
    // can't use invokeLater()
    try
    {
    EventQueue.invokeAndWait( new Runnable()
    {
    public void run()
    {
    JOptionPane.showMessageDialog( null,
    "Another Copy of this Program is Already Running",
    "Start Inhibited", JOptionPane.ERROR_MESSAGE );
    </quote>

    who thinks this conflicts with the Java docs for addShutdownHook
    that states:

    "Attempts to use other thread-based services such as the AWT
    event-dispatch thread, for example, may lead to deadlocks."

    Arne
     
    Arne Vajhøj, Jan 6, 2013
    #16
  17. On 1/5/2013 7:10 PM, Arne Vajhøj wrote:
    > On 1/3/2013 10:12 AM, Roedy Green wrote:
    > <quote>
    > // if we are seeing our own packet, do nothing
    > if ( theirTime == myTime )
    > {
    > </quote>
    >
    > Who can see a concurrency problem in that logic?


    The risk is, that in Windows anyway, where the system clock granularity
    is 17ms it is possible to start two copies of a program with a batch
    file and have them both have the same start time. The risk of doing
    that by hand (which is what I really want to protect against) is, I
    think, infinitesimal.

    > <quote>
    > public void shutdownHook()
    > {
    > // can't use invokeLater()
    > try
    > {
    > EventQueue.invokeAndWait( new Runnable()
    > {
    > public void run()
    > {
    > JOptionPane.showMessageDialog( null,
    > "Another Copy of this Program is Already Running",
    > "Start Inhibited", JOptionPane.ERROR_MESSAGE );
    > </quote>
    >
    > who thinks this conflicts with the Java docs for addShutdownHook
    > that states:
    >
    > "Attempts to use other thread-based services such as the AWT
    > event-dispatch thread, for example, may lead to deadlocks."
    >
    > Arne


    Bad choice of names for my method. It did seem logical when I thought
    it up though. It was not my intent however to have this method called
    from Runtime.shutdownHook(). I don't think I knew this method existed.

    --

    Knute Johnson
     
    Knute Johnson, Jan 6, 2013
    #17
  18. Roedy Green

    Arne Vajhøj Guest

    On 1/5/2013 10:49 PM, Knute Johnson wrote:
    > On 1/5/2013 7:10 PM, Arne Vajhøj wrote:
    >> On 1/3/2013 10:12 AM, Roedy Green wrote:
    >> <quote>
    >> // if we are seeing our own packet, do nothing
    >> if ( theirTime == myTime )
    >> {
    >> </quote>
    >>
    >> Who can see a concurrency problem in that logic?

    >
    > The risk is, that in Windows anyway, where the system clock granularity
    > is 17ms it is possible to start two copies of a program with a batch
    > file and have them both have the same start time. The risk of doing
    > that by hand (which is what I really want to protect against) is, I
    > think, infinitesimal.


    Many concurrency problems are not very likely.

    A lot of people initialized a JFrame based GUI on the main
    thread for years without problems.

    >> <quote>
    >> public void shutdownHook()
    >> {
    >> // can't use invokeLater()
    >> try
    >> {
    >> EventQueue.invokeAndWait( new Runnable()
    >> {
    >> public void run()
    >> {
    >> JOptionPane.showMessageDialog( null,
    >> "Another Copy of this Program is Already
    >> Running",
    >> "Start Inhibited", JOptionPane.ERROR_MESSAGE );
    >> </quote>
    >>
    >> who thinks this conflicts with the Java docs for addShutdownHook
    >> that states:
    >>
    >> "Attempts to use other thread-based services such as the AWT
    >> event-dispatch thread, for example, may lead to deadlocks."

    >
    > Bad choice of names for my method. It did seem logical when I thought
    > it up though. It was not my intent however to have this method called
    > from Runtime.shutdownHook(). I don't think I knew this method existed.


    Ah.

    My mistake.

    I assumed based on the name.

    Assumptions are the mother of all f......!

    Arne
     
    Arne Vajhøj, Jan 6, 2013
    #18
  19. Roedy Green

    Arne Vajhøj Guest

    On 1/5/2013 11:09 PM, Arne Vajhøj wrote:
    > On 1/5/2013 10:49 PM, Knute Johnson wrote:
    >> On 1/5/2013 7:10 PM, Arne Vajhøj wrote:
    >>> On 1/3/2013 10:12 AM, Roedy Green wrote:
    >>> <quote>
    >>> // if we are seeing our own packet, do nothing
    >>> if ( theirTime == myTime )
    >>> {
    >>> </quote>
    >>>
    >>> Who can see a concurrency problem in that logic?

    >>
    >> The risk is, that in Windows anyway, where the system clock granularity
    >> is 17ms it is possible to start two copies of a program with a batch
    >> file and have them both have the same start time. The risk of doing
    >> that by hand (which is what I really want to protect against) is, I
    >> think, infinitesimal.

    >
    > Many concurrency problems are not very likely.
    >
    > A lot of people initialized a JFrame based GUI on the main
    > thread for years without problems.


    And just to be clear: the code may be perfectly fine for your
    specific purpose - I am concerned because Roedy is selling it as
    a general solution when it do have a concurrency problem.

    Arne
     
    Arne Vajhøj, Jan 6, 2013
    #19
  20. Roedy Green

    Lew Guest

    Arne Vajhøj wrote:
    >> Many concurrency problems are not very likely.


    Exactly what makes them so pernicious to fix.

    >> A lot of people initialized a JFrame based GUI on the main
    >> thread for years without problems.


    That kind of thinking in software engineering has actually killed people.
    Horridly and painfully.

    On single-core CPUs, which are no longer so common, threading issues were
    masked. They became evident to the point where Sun had to change the
    instructions not only about initialization but construction, once multi-core
    mobos became common some years ago. They even had to overhaul the entire
    concurrency memory model. So "years without problems" is an utterly specious
    argument.

    > And just to be clear: the code may be perfectly fine for your
    > specific purpose - I am concerned because Roedy is selling it as
    > a general solution when it do have a concurrency problem.


    It may be fine for your specific purpose, but if it has a concurrency bug
    wired in I would not bet on it.

    The point in software engineering is *not* to design for the "maybe there
    won't be a problem this time" scenario.

    --
    Lew
     
    Lew, Jan 6, 2013
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Randall Parker
    Replies:
    1
    Views:
    621
    S. Justin Gengo
    Dec 12, 2005
  2. Chris
    Replies:
    1
    Views:
    13,721
    Oisin
    Mar 24, 2006
  3. chris brat
    Replies:
    1
    Views:
    661
    chris brat
    May 10, 2006
  4. Eric Layman
    Replies:
    3
    Views:
    653
    Rad [Visual C# MVP]
    Apr 14, 2007
  5. goodfella

    single producer, single consumer

    goodfella, Oct 6, 2009, in forum: C++
    Replies:
    41
    Views:
    1,956
    James Kanze
    Oct 12, 2009
Loading...

Share This Page