2003-08-13 05:53:07 +04:00
/* this code is broken - there is a race condition with the unlink (tridge) */
/*
Unix SMB / CIFS implementation .
pidfile handling
Copyright ( C ) Andrew Tridgell 1998
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2007-07-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2003-08-13 05:53:07 +04:00
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
2007-07-10 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2003-08-13 05:53:07 +04:00
*/
# include "includes.h"
2005-02-10 08:09:35 +03:00
# include "system/filesys.h"
2012-07-20 02:41:52 +04:00
# include "lib/util/pidfile.h"
2003-08-13 05:53:07 +04:00
2006-02-28 16:12:39 +03:00
/**
* @ file
* @ brief Pid file handling
*/
/**
* return the pid in a pidfile . return 0 if the process ( or pidfile )
* does not exist
*/
2007-12-03 00:32:11 +03:00
pid_t pidfile_pid ( const char * piddir , const char * name )
2003-08-13 05:53:07 +04:00
{
int fd ;
char pidstr [ 20 ] ;
2012-12-06 19:02:57 +04:00
pid_t ret = - 1 ;
2005-09-26 20:57:08 +04:00
char * pidFile ;
2003-08-13 05:53:07 +04:00
2010-05-27 19:37:15 +04:00
if ( asprintf ( & pidFile , " %s/%s.pid " , piddir , name ) < 0 ) {
return 0 ;
}
2003-08-13 05:53:07 +04:00
2004-11-01 23:21:54 +03:00
fd = open ( pidFile , O_NONBLOCK | O_RDONLY , 0644 ) ;
2005-09-26 20:57:08 +04:00
2003-08-13 05:53:07 +04:00
if ( fd = = - 1 ) {
2005-09-27 15:59:39 +04:00
SAFE_FREE ( pidFile ) ;
2003-08-13 05:53:07 +04:00
return 0 ;
}
2005-02-10 10:39:14 +03:00
ZERO_STRUCT ( pidstr ) ;
2003-08-13 05:53:07 +04:00
if ( read ( fd , pidstr , sizeof ( pidstr ) - 1 ) < = 0 ) {
goto noproc ;
}
2006-04-24 13:36:09 +04:00
ret = ( pid_t ) atoi ( pidstr ) ;
2012-06-28 05:34:25 +04:00
if ( ret < = 0 ) {
2012-07-20 03:08:16 +04:00
DEBUG ( 1 , ( " Could not parse contents of pidfile %s \n " ,
pidFile ) ) ;
2012-06-28 05:34:25 +04:00
goto noproc ;
}
2003-08-13 05:53:07 +04:00
2008-10-17 14:48:19 +04:00
if ( ! process_exists_by_pid ( ret ) ) {
2012-07-20 03:08:16 +04:00
DEBUG ( 10 , ( " Process with PID=%d does not exist. \n " , ( int ) ret ) ) ;
2003-08-13 05:53:07 +04:00
goto noproc ;
}
2004-11-01 23:21:54 +03:00
if ( fcntl_lock ( fd , F_SETLK , 0 , 1 , F_RDLCK ) ) {
2003-08-13 05:53:07 +04:00
/* we could get the lock - it can't be a Samba process */
2012-07-20 03:08:16 +04:00
DEBUG ( 10 , ( " Process with PID=%d is not a Samba process. \n " ,
( int ) ret ) ) ;
2003-08-13 05:53:07 +04:00
goto noproc ;
}
close ( fd ) ;
2005-09-27 15:59:39 +04:00
SAFE_FREE ( pidFile ) ;
2012-07-20 03:08:16 +04:00
DEBUG ( 10 , ( " Process with PID=%d is running. \n " , ( int ) ret ) ) ;
2006-04-24 13:36:09 +04:00
return ret ;
2003-08-13 05:53:07 +04:00
noproc :
close ( fd ) ;
2012-07-20 03:08:16 +04:00
DEBUG ( 10 , ( " Deleting %s, since %d is not a Samba process. \n " , pidFile ,
( int ) ret ) ) ;
2003-08-13 05:53:07 +04:00
unlink ( pidFile ) ;
2005-09-27 15:59:39 +04:00
SAFE_FREE ( pidFile ) ;
2003-08-13 05:53:07 +04:00
return 0 ;
}
2006-02-28 16:12:39 +03:00
/**
* create a pid file in the pid directory . open it and leave it locked
*/
2007-12-03 00:32:11 +03:00
void pidfile_create ( const char * piddir , const char * name )
2003-08-13 05:53:07 +04:00
{
int fd ;
char buf [ 20 ] ;
2005-09-26 20:57:08 +04:00
char * pidFile ;
2003-08-13 05:53:07 +04:00
pid_t pid ;
2010-05-27 19:37:15 +04:00
if ( asprintf ( & pidFile , " %s/%s.pid " , piddir , name ) < 0 ) {
DEBUG ( 0 , ( " ERROR: Out of memory \n " ) ) ;
exit ( 1 ) ;
}
2003-08-13 05:53:07 +04:00
2007-12-03 00:32:11 +03:00
pid = pidfile_pid ( piddir , name ) ;
2003-08-13 05:53:07 +04:00
if ( pid ! = 0 ) {
DEBUG ( 0 , ( " ERROR: %s is already running. File %s exists and process id %d is running. \n " ,
name , pidFile , ( int ) pid ) ) ;
exit ( 1 ) ;
}
2004-11-01 23:21:54 +03:00
fd = open ( pidFile , O_NONBLOCK | O_CREAT | O_WRONLY | O_EXCL , 0644 ) ;
2003-08-13 05:53:07 +04:00
if ( fd = = - 1 ) {
DEBUG ( 0 , ( " ERROR: can't open %s: Error was %s \n " , pidFile ,
strerror ( errno ) ) ) ;
exit ( 1 ) ;
}
2011-12-17 20:04:09 +04:00
smb_set_close_on_exec ( fd ) ;
2011-11-30 08:18:54 +04:00
2007-10-02 02:13:02 +04:00
if ( fcntl_lock ( fd , F_SETLK , 0 , 1 , F_WRLCK ) = = false ) {
2003-08-13 05:53:07 +04:00
DEBUG ( 0 , ( " ERROR: %s : fcntl lock of file %s failed. Error was %s \n " ,
name , pidFile , strerror ( errno ) ) ) ;
exit ( 1 ) ;
}
memset ( buf , 0 , sizeof ( buf ) ) ;
2006-04-24 13:36:09 +04:00
slprintf ( buf , sizeof ( buf ) - 1 , " %u \n " , ( unsigned int ) getpid ( ) ) ;
2003-08-13 05:53:07 +04:00
if ( write ( fd , buf , strlen ( buf ) ) ! = ( ssize_t ) strlen ( buf ) ) {
DEBUG ( 0 , ( " ERROR: can't write to file %s: %s \n " ,
pidFile , strerror ( errno ) ) ) ;
exit ( 1 ) ;
}
2005-09-26 20:57:08 +04:00
2003-08-13 05:53:07 +04:00
/* Leave pid file open & locked for the duration... */
2005-09-26 20:57:08 +04:00
SAFE_FREE ( pidFile ) ;
2003-08-13 05:53:07 +04:00
}
2012-07-20 03:08:16 +04:00
void pidfile_unlink ( const char * piddir , const char * name )
{
int ret ;
char * pidFile = NULL ;
if ( asprintf ( & pidFile , " %s/%s.pid " , piddir , name ) < 0 ) {
DEBUG ( 0 , ( " ERROR: Out of memory \n " ) ) ;
exit ( 1 ) ;
}
ret = unlink ( pidFile ) ;
if ( ret = = - 1 ) {
DEBUG ( 0 , ( " Failed to delete pidfile %s. Error was %s \n " ,
pidFile , strerror ( errno ) ) ) ;
}
}