fcloseall() on Solaris

All

I have a program that loads an Oracle shared object, after performing a truss on the process I noticed that Oracle is not closing all the files it is opening, thus after numerous iterations (255 unclosed file handles) the program quits responding to any future file requests... Thus I want to attempt to close these left open file handles after they are done being used... I have read about a function fcloseall() that should help in accomplishing what I am trying to do, however, I can not get it to work on Solaris 8... At compile time I get an undefined symbol... Does anyone either know how to get fcloseall() to work on Solaris, or have a piece of code that will accomplish this (i.e. closing all file handles generated by the current proces or subprocesses)?

Best regards
echard
echardAsked:
Who is Participating?
 
Kent OlsenData Warehouse Architect / DBACommented:

>>what is the easiest way to determine the current value of NFILES

C assigns file handles incrementally starting with the lowest available handle.  Since you believe that Oracle is never closing a file you can open a file which should therefore return a handle one higher than the last one used by Oracle.  The use this handle as the upper limit.

int  UpperLimit;
int  idx;

  UpperLimit = open ("LimitCheck", O_CREAT|O_TRUNC);
  for (idx = 3; i <= UpperLimit; close (idx++));


Kent
0
 
jkrCommented:
See the 'fcloseall()' manpage:

NAME
       fcloseall - close all open streams

SYNOPSIS
       #define _GNU_SOURCE

       #include <stdio.h>

       int fcloseall(void);

DESCRIPTION
       The  fcloseall  function dissociates all open streams from
       its underlying file or set  of  functions.   Any  buffered
       output  data is written first, using fflush(3).  Note that
       the standard streams (stdin, stdout and stderr)  are  also
       closed.

RETURN VALUE
       This function always returns 0.

SEE ALSO
       fclose(3), close(2), fflush(3), fopen(3), setbuf(3)

CONFORMING TO
       The fcloseall function is a GNU extension. <-------!


This means that unless you can use gcc and its runtime library, you are pretty much lost.
0
 
Kent OlsenData Warehouse Architect / DBACommented:
Hi echard,

I'm going to caution you that fcloseall() is inherently dangerous and will very likely not produce the effect that you seek.

fcloseall() closes ALL the streams associated with your task.  This includes stdin, stdout, and stderr.  Many library routines depend on these standard streams so you would have to immediately reopen these streams to prevent a routine from attempting I/O to a standard stream only to find that the FILE pointer now contains garbage.

Can you guarantee that the other streams are abandoned?  Closing a stream (or file handle) when another portion of the application is expecting a valid pointer can also be catastrophic.

My suggestion would be to structure your program so that it fork()s off a child process that handles the Oracle interface.  Data is passed to/from parent and child via pipes.  Your application is free to operate in a rational manner while the child task(s) get to handle all of the I/O including the database interfaces.  Open streams are automatically closed when the child terminates so the ugly side effects that you're seeing now can be avoided.


Kent
0
Get expert help—faster!

Need expert help—fast? Use the Help Bell for personalized assistance getting answers to your important questions.

 
jkrCommented:
>>fcloseall() closes ALL the streams associated with your task.

That's why I did not suggest 'for ( int i = 3; i < NFILES; close (i++));' as a workaround :o)
0
 
Kent OlsenData Warehouse Architect / DBACommented:

Hi jkr,

Yeah... There is no good and easy solution to his problem.

Much like most code involving Oracle.  :)

kent
0
 
echardAuthor Commented:
All

I was under the impressions that fcloseall() would leave stdin, stdout, stderr all open and close all other files. However I accept what you said above Kent and jkr... The only good thing about this mess is that I know that I can safely close all file handles above the stdin, stdout, stderr handles (0,1,2) thus a solution similar to jkr's of 'for ( int i = 3; i < NFILES; close (i++));'  may work as an ugly fix until Oracle addresses the issue. I do realize and jkr please forgive this statement that it is an ugly solution and highly undesirable, but it is pertinent that I get these open file handles closed before reaching the soft limit of 256...

I do have a question assuming I use jkr's solution what is the easiest way to determine the current value of NFILES... in other words is it a macro that contains the value? where is it defined? etc...

Kent

I have thought about forking a child process, however that solution is goint o take a little time to implement and I need a short term solution.

Guys please provide thoughts as desired.

echard
0
 
jkrCommented:
>>what is the easiest way to determine the current value of NFILES

You answered that by writing 'before reaching the soft limit of 256...' :o)

However, this method is not recommended, even though it is common practise when starting a daemon...

0
 
echardAuthor Commented:
Kent and jkr

Thanks for all of your help to this point...

The more I think about it I am wondering if there is a way to close all open file handles pointing to a specific file... For example on of the problem files in {$ORACLE_HOME}/xdk/xdk/mesg/lsxus.msb that is being left open is there a way that either of you may be aware of to "query" for all open file handles that end in *.msb and get the file id for them and then close them accordingly? Just thinking this may be way safer since I am using such an undesirable approach to begin with...

Thoughts?

echard
0
 
sunnycoderCommented:
>The more I think about it I am wondering if there is a way to close all open file handles pointing to a specific file
do you have /proc file system on solaris ... or some equivalent information source ...

if yes, then

/proc/<pid>/fd
has list of all fds and their corresponding files ... you need to parse the result , search for the specific file and close all associated fds
0
 
imstaffCommented:
This function is an extension to fclose. Even though Solaris supports fclose, fcloseall is not supported. You can use fclose to implement fcloseall: Assuming there is an array of FILE *streams, called fileNamePtr[i]:

for(i = 0; i < MAXSTREAMS; i++)
     fclose(fileNamePtr[i]);
0
 
jkrCommented:
Um, why if I may ask?
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.