Determine if only one instance is running: Difference between revisions

From Rosetta Code
Content added Content deleted
(Go solution)
(Added BBC BASIC)
Line 5: Line 5:
=={{header|AutoHotkey}}==
=={{header|AutoHotkey}}==
AutoHotkey has a #SingleInstance command. If you run two scripts that don't have it at the same time, it alerts the user. #SingleInstance FORCE closes the older instance when a newer one is run, and #SingleInstance IGNORE does nothing when you try to open a new instance of an already-running script.
AutoHotkey has a #SingleInstance command. If you run two scripts that don't have it at the same time, it alerts the user. #SingleInstance FORCE closes the older instance when a newer one is run, and #SingleInstance IGNORE does nothing when you try to open a new instance of an already-running script.

=={{header|BBC BASIC}}==
Change 'UniqueLockName' to something more likely to be unique, such as a GUID.
<lang BBC BASIC> SYS "CreateMutex", 0, 1, "UniqueLockName" TO Mutex%
SYS "GetLastError" TO lerr%
IF lerr% = 183 THEN
SYS "CloseHandle", Mutex%
SYS "MessageBox", @hwnd%, "I am already running", 0, 0
QUIT
ENDIF
SYS "ReleaseMutex", Mutex%
SYS "CloseHandle", Mutex%
END</lang>


=={{header|C}}==
=={{header|C}}==

Revision as of 16:33, 17 May 2011

Task
Determine if only one instance is running
You are encouraged to solve this task according to the task description, using any language you may know.

This task is to determine if there is only one instance of an application running. If the program discovers that an instance of it is already running, then it should display a message indicating that it is already running and exit.

AutoHotkey

AutoHotkey has a #SingleInstance command. If you run two scripts that don't have it at the same time, it alerts the user. #SingleInstance FORCE closes the older instance when a newer one is run, and #SingleInstance IGNORE does nothing when you try to open a new instance of an already-running script.

BBC BASIC

Change 'UniqueLockName' to something more likely to be unique, such as a GUID. <lang BBC BASIC> SYS "CreateMutex", 0, 1, "UniqueLockName" TO Mutex%

     SYS "GetLastError" TO lerr%
     IF lerr% = 183 THEN
       SYS "CloseHandle", Mutex%
       SYS "MessageBox", @hwnd%, "I am already running", 0, 0
       QUIT
     ENDIF
     
     SYS "ReleaseMutex", Mutex%
     SYS "CloseHandle", Mutex%
     END</lang>

C

POSIX with file lock

This solution opens ~/rosetta-code-lock and uses fcntl() to set a write lock on the file. Only one instance can set this lock. If fcntl() fails, this program assumes that another instance is running. This program always clears its lock when it terminates.

The user might use an interrupt or other signal to terminate the program. If so, the lock file survives, but the system still clears the lock. The user can run the program again.

Library: POSIX

<lang c>#include <fcntl.h> /* fcntl, open */

  1. include <stdlib.h> /* atexit, getenv, malloc */
  2. include <stdio.h> /* fputs, printf, puts, snprintf */
  3. include <string.h> /* memcpy */
  4. include <unistd.h> /* sleep, unlink */

/* Filename for only_one_instance() lock. */

  1. define INSTANCE_LOCK "rosetta-code-lock"

void fail(const char *message) { perror(message); exit(1); }

/* Path to only_one_instance() lock. */ static char *ooi_path;

void ooi_unlink(void) { unlink(ooi_path); }

/* Exit if another instance of this program is running. */ void only_one_instance(void) { struct flock fl; size_t dirlen; int fd; char *dir;

/* * Place the lock in the home directory of this user; * therefore we only check for other instances by the same * user (and the user can trick us by changing HOME). */ dir = getenv("HOME"); if (dir == NULL || dir[0] != '/') { fputs("Bad home directory.\n", stderr); exit(1); } dirlen = strlen(dir);

ooi_path = malloc(dirlen + sizeof("/" INSTANCE_LOCK)); if (ooi_path == NULL) fail("malloc"); memcpy(ooi_path, dir, dirlen); memcpy(ooi_path + dirlen, "/" INSTANCE_LOCK, sizeof("/" INSTANCE_LOCK)); /* copies '\0' */

fd = open(ooi_path, O_RDWR | O_CREAT, 0600); if (fd < 0) fail(ooi_path);

fl.l_start = 0; fl.l_len = 0; fl.l_type = F_WRLCK; fl.l_whence = SEEK_SET; if (fcntl(fd, F_SETLK, &fl) < 0) { fputs("Another instance of this program is running.\n", stderr); exit(1); }

/* * Run unlink(ooi_path) when the program exits. The program * always releases locks when it exits. */ atexit(ooi_unlink); }

/*

* Demo for Rosetta Code.
* http://rosettacode.org/wiki/Determine_if_only_one_instance_is_running
*/

int main() { int i;

only_one_instance();

/* Play for 10 seconds. */ for(i = 10; i > 0; i--) { printf("%d...%s", i, i % 5 == 1 ? "\n" : " "); fflush(stdout); sleep(1); } puts("Fin!"); return 0; }</lang>

POSIX with file creation

This solution opens a file with O_CREAT|O_EXCL. If the file already exists, this program assumes that another instance is running. This solution is not as good as file locking, because the program might terminate without deleting the file.

The program, when terminating, must be sure to unlink() the file. This example has unlink() at two places: at the end of main(), and at a SIGINT handler. If you interrupt the program, it will probably delete /tmp/MyUniqueName, but not if SIGINT wins a race before the program installs its handler. If you terminate the program with a different signal, then you will get stuck, because /tmp/MyUniqueName will still exist, preventing another execution of the program. One might add code to catch some other signals, but there is no way to catch SIGKILL!

This program uses a regular file, with open() and unlink(). There is an older version that uses a semaphore, with sem_open() and sem_unlink(). The switch from a semaphore to a regular file was easy, because the program never used the semaphore as a semaphore; it only checked the existence of a semaphore. If you get stuck, rm /tmp/MyUniqueName might be easier than deleting a semaphore.

Library: POSIX

<lang c>#include <fcntl.h>

  1. include <signal.h>
  2. include <stdio.h>
  3. include <stdlib.h>
  4. include <unistd.h>

/* unistd for sleep */

void sigint_handler(int sig) {

  fprintf(stderr, "Caught signal %d.\n", sig);
  unlink("/tmp/MyUniqueName");
  /* exit() is not safe in a signal handler, use _exit() */
  _exit(1);

}

int main() {

  struct sigaction act;
  int myfd;
  
  myfd = open("/tmp/MyUniqueName", O_CREAT|O_EXCL);
  if ( myfd < 0 )
  {
     fprintf(stderr, "I am already running!\n");
     exit(1);
  }
  act.sa_handler = sigint_handler;
  sigemptyset(&act.sa_mask);
  act.sa_flags = 0;
  sigaction(SIGINT, &act, NULL);
  /* here the real code of the app*/
  sleep(20);
  /* end of the app */
  unlink("/tmp/MyUniqueName"); close(myfd);
  return 0;

}</lang>

C++

Microsoft Windows

Works with: Windows version 2000 or later

This line needs to be near the top of the file (or in stdafx.h, if you use one.) <lang cpp>#include <afx.h></lang>

You need a variable of type HANDLE with the same lifetime as your program. Perhaps as a member of your CWinApp object. <lang cpp>HANDLE mutex;</lang>

At the earliest possible point in your program, you need to initialize it and perform your check. "MyApp" should be a string unique to your application. See here for full details.

<lang cpp>mutex = CreateMutex( NULL, TRUE, "MyApp" ); if ( GetLastError() == ERROR_ALREADY_EXISTS ) {

    // There's another instance running.  What do you do?

}</lang>

Finally, near the end of your program, you need to close the mutex. <lang cpp>CloseHandle( mutex );</lang>

C#

<lang csharp>using System; using System.Net; using System.Net.Sockets;

class Program {

   static void Main(string[] args) {        
       try {
           TcpListener server = new TcpListener(IPAddress.Any, 12345);
           server.Start();
       } 
      
       catch (SocketException e) {
           if (e.SocketErrorCode == SocketError.AddressAlreadyInUse) {
               Console.Error.WriteLine("Already running.");
           }
       }
   }

}</lang>

Clojure

Translation of: Java

<lang clojure>(import (java.net ServerSocket InetAddress))

(def *port* 12345) ; random large port number (try (new ServerSocket *port* 10 (. InetAddress getLocalHost))

    (catch IOException e (System/exit 0))) ; port taken, so app is already running </lang>

Go

Solution using O_CREATE|O_EXCL, and with messages and a 10 second sleep to let you test it. <lang go>package main

import (

   "fmt"
   "os"
   "strconv"
   "strings"
   "time"

)

// The path to the lock file should be an absolute path starting from the root. // (If you wish to prevent the same program running in different directories, that is.) const lfn = "/tmp/rclock"

func main() {

   lf, err := os.OpenFile(lfn, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666)
   if err == nil {
       // good
       // 10 digit pid seems to be a standard for lock files
       fmt.Fprintf(lf, "%10d", os.Getpid())
       lf.Close()
       defer os.Remove(lfn)
   } else {
       // problem
       fmt.Println(err)
       // dig deeper
       lf, err = os.Open(lfn)
       if err != nil {
           return
       }
       defer lf.Close()
       fmt.Println("inspecting lock file...")
       b10 := make([]byte, 10)
       _, err = lf.Read(b10)
       if err != nil {
           fmt.Println(err)
           return
       }
       pid, err := strconv.Atoi(strings.TrimSpace(string(b10)))
       if err != nil {
           fmt.Println(err)
           return
       }
       fmt.Println("lock file created by pid", pid)
       return
   }
   fmt.Println(os.Getpid(), "running...")
   time.Sleep(1e10)

}</lang>

Java

<lang java>import java.io.IOExeception; import java.net.InetAddress; import java.net.ServerSocket; import java.net.UnknownHostException;

public class SingletonApp { private static final int PORT = 12345; // random large port number private static ServerSocket s;

// static initializer { try { s = new ServerSocket(PORT, 10, InetAddress.getLocalHost()); } catch (UnknownHostException e) { // shouldn't happen for localhost } catch (IOException e) { // port taken, so app is already running System.exit(0); } } // main() and rest of application... }</lang>

Liberty BASIC

<lang lb>'Create a Mutex to prevent more than one instance from being open at a single time. CallDLL #kernel32, "CreateMutexA", 0 as Long, 1 as Long, "Global\My Program" as ptr, mutex as ulong CallDLL #kernel32, "GetLastError", LastError as Long

if LastError = 183 then 'Error returned when a Mutex already exists

   'Close the handle if the mutex already exists
   calldll #kernel32, "CloseHandle", mutex as ulong, ret as ulong
   notice "An instance of My Program is currently running!"
   end

end if

'Release the Mutex/ Close the handle prior to ending the program 'Comment out these lines to allow the program to remain active to test for the mutex's presence calldll #kernel32, "ReleaseMutex", mutex as ulong, ret as ulong calldll #kernel32, "CloseHandle", mutex as ulong, ret as ulong end</lang>

OCaml

Replicates the C example, with the library ocaml-sem. <lang ocaml>open Sem

let () =

 let oflags = [Unix.O_CREAT;
               Unix.O_EXCL] in
 let sem = sem_open "MyUniqueName" ~oflags () in
 (* here the real code of the app *)
 Unix.sleep 20;
 (* end of the app *)
 sem_unlink "MyUniqueName";
 sem_close sem</lang>

The standard library of OCaml also provides a Mutex module.

Oz

<lang oz>functor import Application Open System define

  fun {IsAlreadyRunning}
     try

S = {New Open.socket init}

     in

{S bind(takePort:12345)} false

     catch system(os(os "bind" ...) ...) then

true

     end
  end
  if {IsAlreadyRunning} then
     {System.showInfo "Exiting because already running."}
     {Application.exit 1}
  end
  {System.showInfo "Press enter to exit."}
  {{New Open.file init(name:stdin)} read(list:_ size:1)}
  {Application.exit 0}

end</lang>

Perl

The INIT block is runned just before the Perl runtime begins execution. See perlmod

Then it tries to get a lock to its own file, from where the script was called. <lang perl>use Fcntl ':flock';

INIT { die "Not able to open $0\n" unless (open ME, $0); die "I'm already running !!\n" unless(flock ME, LOCK_EX|LOCK_NB); }

sleep 60; # then your code goes here</lang>

PicoLisp

Calling 'killall'

One possibility is to send a zero-signal with 'killall', and check the return value. This is useful if each application is started by a hash-bang script (the first line is e.g. "#!/usr/bin/picolisp /usr/lib/picolisp/lib.l"). In that way, each application has its onw name which can be passed to 'killall'.

$ cat myScript
#!/usr/bin/picolisp /usr/lib/picolisp/lib.l

(wait 120000)
(bye)
$ ./myScript &  # Start in the background
[1] 26438

<lang PicoLisp>$ ./dbg

(call "killall" "-0" "-q" "myScript")

-> T</lang>

Using a mutex

Another possibility is to 'acquire' a mutex on program start, and never release it. <lang PicoLisp>: (acquire "running1") -> 30817 # A successful call returns the PID</lang> A second application trying to acquire the same mutex would receive 'NIL'

PureBasic

<lang PureBasic>#MyApp="MyLittleApp" Mutex=CreateMutex_(0,1,#MyApp) If GetLastError_()=#ERROR_ALREADY_EXISTS

 MessageRequester(#MyApp,"One instance is already started.")
 End

EndIf

Main code executes here

ReleaseMutex_(Mutex) End</lang>

Python

Linux (including cygwin) and Mac OSX Leopard

Works with: Python version 2.6

Must be run from an application, not the interpreter.

<lang python>import __main__, os

def isOnlyInstance():

   # Determine if there are more than the current instance of the application
   # running at the current time.
   return os.system("(( $(ps -ef | grep python | grep '[" +
                    __main__.__file__[0] + "]" + __main__.__file__[1:] +
                    "' | wc -l) > 1 ))") != 0</lang>

This is not a solution - one can run the same app by copying the code to another location. A solution may be a lock file or lock directory created by the first instance and hold while the first instance is running.

Ruby

Uses file locking on the program file <lang ruby>def main

 puts "first instance"
 sleep 20
 puts :done

end

if $0 == __FILE__

 if File.new(__FILE__).flock(File::LOCK_EX | File::LOCK_NB)
   main
 else
   raise "another instance of this program is running"
 end

end

__END__</lang>

Tcl

Translation of: Java
Works with: Tcl version 8.6

<lang Tcl>package require Tcl 8.6 try {

   # Pick a port number based on the name of the main script executing
   socket -server {apply {{chan args} {close $chan}}} -myaddr localhost \
           [expr {1024 + [zlib crc32 [file normalize $::argv0]] % 30000}]

} trap {POSIX EADDRINUSE} {} {

   # Generate a nice error message
   puts stderr "Application $::argv0 already running?"
   exit 1

}</lang>

UNIX Shell

Works with: Bourne Shell
Works with: Bourne Again SHell

<lang sh>

  1. (c) Copyright 2005 Mark Hobley
  2. This is free software. This file can be redistributed or modified
  3. under the terms of version 1.2 of the GNU Free Documentation Licence
  4. as published by the Free Software Foundation.
singleinstance ()
{
  if [ -d $SRUNDIR ] ; then
    if [ -w $SRUNDIR ] ; then
      if [ -d $SRUNDIR/$APPNAME ] ; then
        echo "Process Already Running" >& 2
        return 221
      else
        mkdir $SRUNDIR/$APPNAME
        if [ "$?" -ne 0 ] ; then
          if [ -d $SRUNDIR/$APPNAME ] ; then
            echo "Process Already Running" >& 2
            return 221
          else
            echo "Unexpected Error" >& 2
            return 239
          fi
        fi
        return 0 ; # This is a unique instance
      fi
    else
      echo "Permission Denied" >& 2
      return 210
    fi
  else
    echo "Missing Directory" >& 2
    return 199
  fi
}

</lang>

Visual Basic

Works with: Visual Basic version 6

<lang vb>Dim onlyInstance as Boolean onlyInstance = not App.PrevInstance</lang>