ACE C++ Log in multiple files - c++

I'm diving through ACE and, I'm logging message in a file using the ACE_ERROR macro.
And AFAIK, ACE_ERROR logs all the messages in the same file, regardless of their error level.
However, I actually need to write messages, according to their error level.
I did see the ACE_LOG_MSG->open() function however, what i understand is that when you already calling this function twice, the second time it will close the file you opened when you called the function at the beginning.
Suppose I have a list and I want to log it and, in this list, two adjacent items don't have the same error level.
Then I would be opening and closing files, wouldn't than affect my apps performance ?
So is there a way to keep those files open ?
Thanks !

Not closing the files you log to is particularly bad in debugging. If the application crashes with an open file, its contents may (and that happens rather often) get corrupted, leaving you with absolutely no information.
If you close the file properly, though, you're guaranteed to find at least some info there, possibly closer to the real issue. If you are concerned with performance, you should simply reduce log level, or if it's not feasible, you could perhaps offload the logging to the other process via (for example) TCP connection.
Anyway, don't optimize until you've measured! It might just be there'll be no impact, performance is a complicated problem which depends on lot of factors.

Another example to re-direct logging as per their logging priority, using a simple wrapper class.
Hope this is useful to someone.
Example program
#include "ace/Log_Msg.h"
#include "ace/streams.h"
// #Author: Gaurav A
// #Date: 2019OCT11
//
// Log each logging statement
// in file based on its priority
//
// eg: INFO logs goes to INFO.log
// DEBUG logs goes to DEBUG.log
class Logger
{
private:
ACE_OSTREAM_TYPE* m_infolog=nullptr;
ACE_OSTREAM_TYPE* m_debuglog=nullptr;
public:
Logger(void)
: m_infolog (new std::ofstream ("INFO.log")),
m_debuglog (new std::ofstream ("DEBUG.log"))
{
}
~Logger(void)
{
delete m_infolog;
delete m_debuglog;
}
int log (ACE_Log_Priority p,
const ACE_TCHAR* fmt,
...)
{
ssize_t final_result=0;
if (p == LM_DEBUG)
{
va_list argp;
va_start (argp, fmt);
ACE_LOG_MSG->msg_ostream (m_debuglog);
ACE_LOG_MSG->set_flags (ACE_Log_Msg::OSTREAM);
final_result = ACE_LOG_MSG->log (fmt, LM_DEBUG, argp);
va_end (argp);
}
else if (p == LM_INFO)
{
va_list argp;
va_start (argp, fmt);
ACE_LOG_MSG->msg_ostream (m_infolog);
ACE_LOG_MSG->set_flags (ACE_Log_Msg::OSTREAM);
final_result = ACE_LOG_MSG->log (fmt, LM_INFO, argp);
va_end (argp);
}
return final_result;
}
};
int
ACE_TMAIN (void)
{
Logger logger;
logger.log (LM_DEBUG, "I am a debug message no %d\n", 1);
logger.log (LM_INFO, "I am a info message no %d\n", 2);
logger.log (LM_DEBUG, "I am a debug message no %d\n", 3);
logger.log (LM_INFO, "I am a info message no %d\n", 4);
return 0;
}
Sample Output
[07:59:10]Host#User:~/acedir
$: ./logging_each_priority_in_its_own_file
I am a debug message no 1
I am a info message no 2
I am a debug message no 3
I am a info message no 4
[07:59:10]Host#User:~/acedir
$: ls -lrth
total 464K
-rw-r--r-- 1 aryaaur devusers 231 Oct 11 07:09 logging_each_priority_in_its_own_file.mpc
-rw-r--r-- 1 aryaaur devusers 5.6K Oct 11 07:29 GNUmakefile.logging_each_priority_in_its_own_file
-rw-r--r-- 1 aryaaur devusers 1.5K Oct 11 07:47 main_logging_each_priority_in_its_own_file_20191011.cpp
-rwxr-xr-x 1 aryaaur devusers 65K Oct 11 07:47 logging_each_priority_in_its_own_file
-rw-r--r-- 1 aryaaur devusers 50 Oct 11 07:59 INFO.log
-rw-r--r-- 1 aryaaur devusers 52 Oct 11 07:59 DEBUG.log
[07:59:10]Host#User:~/acedir
$: cat INFO.log
I am a info message no 2
I am a info message no 4
[07:59:10]Host#User:~/acedir
$: cat DEBUG.log
I am a debug message no 1
I am a debug message no 3
[07:59:10]Host#User:~/acedir
$:

Related

C/C++ - How to make a singleton connection module in Apache HTTP Server?

Let's say I have this code for my apache module:
#include <iostream>
#include <string>
#include <httpd.h>
#include <http_core.h>
#include <http_protocol.h>
#include <http_request.h>
#include <apr_strings.h>
int count = 0;
static void my_child_init(apr_pool_t *p, server_rec *s)
{
count = 1000; //starts up with this number!
}
static int my_handler(request_rec *r)
{
count++; //Increments here
ap_rputs(std::to_string(count).c_str(), r);
return OK;
}
static void register_hooks(apr_pool_t *pool)
{
ap_hook_child_init(my_child_init, NULL, NULL, APR_HOOK_MIDDLE);
ap_hook_handler(my_handler, NULL, NULL, APR_HOOK_LAST);
}
module AP_MODULE_DECLARE_DATA myserver_module =
{
STANDARD20_MODULE_STUFF,
NULL, // Per-directory configuration handler
NULL, // Merge handler for per-directory configurations
NULL, // Per-server configuration handler
NULL, // Merge handler for per-server configurations
NULL, // Any directives we may have for httpd
register_hooks // Our hook registering function
};
Now if I open my browser and go to localhost/my_server I see my count incrementing every time I refresh my page, creating a new HTTP request to Apache.
1001 //from connection 1
1002 //from connection 1
1003 //from connection 1
1004 //from connection 1
...
I was expecting that everytime I refresh, I see the count incrementing. But sometimes I see that apache probably created another connection and the module is instantiated again.. and I have now two equal connections running:
1151 //from connection 1
1152 //from connection 1
1001 // from connection 2
1153 //from connection 1
1002 // from connection 2
1003 // from connection 2
1154 //from connection 1
...
Is there anyway I prevent apache reloading the same module?
Most Apache MPM / common configurations will create multiple child processes. You can configure them to use a single process with many threads instead, or use shared memory for your counter.
The simplest way to use shared memory in a portable way is to depend on the "slotmem" and "slotmem_shm" modules. mod_proxy_balancer uses this. An alternate way is to how server/scoreboard.c uses shared memory directly.

How do I change the creation time of a file to a newer date in Mac OS X?

On Mac OS X, using C and/or C++, I want to change the creation time of a file to an arbitrary date/time. I have found a number of solutions, notably this StackOverflow answer, that allow to set the creation time to an older date, but this is not sufficient for me - I also want to be able to set a newer date. Using the utimes() function therefore is not the solution I am looking for.
I know that setting a newer creation time must be possible somehow, because the SetFile utility from Apple's developer command line tools can do it, but so far my search-fu has failed to uncover any hints that bring me closer to a solution.
Does anyone know of a way how I can achieve my goal?
Why do I want to do this myself, why can't I use SetFile?
The SetFile command line utility is deprecated (see man SetFile), so it's bound to go away some time in the future
I want to create a utility that allows me to specify a time delta to add to/subtract from the current creation time. The SetFile utility does not have any convenient command line arguments to do this.
Last but not least: Curiosity!
Haven't tried it, but according to the docs, the NSURL resource value under the key NSURLCreationDateKey is read-write. Since you specified C or C++, you'd use the corresponding CFURL API. So, you'd call:
CFURLRef url = /* ... */
CFDateRef date = /* ... */
CFErrorRef error;
if (!CFURLSetResourcePropertyForKey(url, kCFURLCreationDateKey, date, &error))
/* handle error */;
EDIT: A minimal example
const char* fileName = "/path/to/file";
size_t fileNameStringLength = strlen(fileName);
Boolean isDirectory = false;
CFURLRef url = CFURLCreateFromFileSystemRepresentation(
kCFAllocatorDefault,
(const UInt8*)fileName,
fileNameStringLength,
isDirectory);
// Seconds since 1 January, 2001 00:00:00 GMT
CFAbsoluteTime absTime = CFAbsoluteTimeGetCurrent();
CFAbsoluteTime adjustedCreationTime = absTime - 3600;
CFDateRef date = CFDateCreate(
kCFAllocatorDefault,
adjustedCreationTime);
CFErrorRef error;
if (!CFURLSetResourcePropertyForKey(url, kCFURLCreationDateKey, date, &error))
{
fprintf(stderr, "an error occurred\n");
exit(1);
}
CFRelease(url);
CFRelease(date);
BTW, I have no idea if this is safe, secure, whatever. So, do this at your own risk.
On OS X, you can sort of do this by setting the time of the day to the future and then copying the file (and renaming it back). It is not the same file with its creation time modified; it is a copy with the creation time you set.
Some code (I got the code to set the time of the day from here):
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <copyfile.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
struct timeval tv_now, tv_set;
copyfile_state_t s;
struct stat st;
// retrieve original stat
if (stat(argv[2], &st) < 0)
perror("stat");
// get current time of day
if (gettimeofday(&tv_now, 0) == -1)
perror("gettimeofday");
// set time of day to +argv[1] days
tv_set = tv_now;
tv_set.tv_sec += 86400 * atoi(argv[1]);
if (settimeofday(&tv_set, 0) == -1)
perror("settimeofday to future");
// copy the file to a temporary, copy everythig except stat
s = copyfile_state_alloc();
if (copyfile(argv[2], ".eighty_eight_miles_per_hour", s, COPYFILE_ACL | COPYFILE_XATTR | COPYFILE_DATA) < 0)
perror("copy file");
copyfile_state_free(s);
// rename it back to original name
if (rename(".eighty_eight_miles_per_hour", argv[2]) < 0)
perror("rename file");
// restore file owner, group, and mode
if (chown(argv[2], st.st_uid, st.st_gid) < 0)
perror("chown");
if (chmod(argv[2], st.st_mode) < 0)
perror("chmod");
// reset current time of day
if (settimeofday(&tv_now, 0) == -1)
perror("settimeofday back to now");
return 0;
}
I call this program the flux_capacitor. The first command line argument is the number of days forward to set the file's creation date, and the second argument is the file name. You have to run this program as root to set the time.
Observe, as I send the delorean forward in time by 2 days.
[ronin:~/Documents/CPP] aichao% touch delorean
[ronin:~/Documents/CPP] aichao% ls -l delorean
-rw-r--r-- 1 aichao staff 0 Aug 10 11:43 delorean
[ronin:~/Documents/CPP] aichao% su
Password:
sh-3.2# ./flux_capacitor 2 delorean
sh-3.2# exit
exit
[ronin:~/Documents/CPP] aichao% ls -l delorean
-rw-r--r-- 1 aichao staff 0 Aug 12 2016 delorean
[ronin:~/Documents/CPP] aichao% date
Wed Aug 10 11:43:47 EDT 2016
and in the Finder:
Note that I only restore the original owner, group, and mode from the stat for the file. I don't think you can or want to do more than that, but I don't know. Obviously, links to the file will be broken.

select() from other thread not handle incoming data

I have multithread applications. In one thread I want to waiting for data, and if this datas will not appear through some time, I just close whole application. Function select() is runs in another thread and thread is detach
A piece sorce some class
#define STDIN 0
A::A(){
runFunction1();
runFunction2();
thread listen(&A::isData , this);
listen.detach();
}
// and function with select
void A::isData{
struct timeval tv;
fd_set readfds;
tv.tv_sec = 50; // wait to 50 seconds
tv.tv_usec = 500000;
FD_ZERO(&readfds);
FD_SET(STDIN, &readfds);
for(;;) {
select(STDIN+1, &readfds, NULL, NULL, &tv);
if (FD_ISSET(STDIN, &readfds)){
cout << "I something catch :)" << endl;
// reset time
}else{
cout << "I nothing catch ! By By :(" << endl;
exit(1);
break;
}
}
}
If my program run then I get pid, so I have tryed write to file descriptor some datas in below way:
$ cd /proc/somePID/fd
$ echo 1 >> 0
Then I should be get info I something catch :) but in console IDE I only get 1 , however if time is out I get I nothing catch ! By By :( to console in IDE.
EDIT: SOLVED
#Vladimir Kunschikov gave me correct tip. Basic on this I show how I do it in C/C++
It will be posible send something to process using command echo we must create pipe. Pipe using function
A::A(){
fd[2]; //two file descriptor for pipes write/read
pipe(fd); // c function to create pipes
runFunction1();
runFunction2();
thread listen(&A::isData , this);
listen.detach();
}
Then in our proces will create other two new file descriptor as below:
lrwx------ 1 user user 64 gru 15 14:02 0 -> /dev/pts/0
lrwx------ 1 user user 64 gru 15 14:02 1 -> /dev/pts/0
lrwx------ 1 user user 64 gru 15 14:02 2 -> /dev/pts/1
lr-x------ 1 user user 64 gru 15 14:02 3 -> pipe:[1335197]
lrwx------ 1 user user 64 gru 15 14:02 4 -> socket:[1340788]
l-wx------ 1 user user 64 gru 15 14:02 5 -> pipe:[1335197]
pipe:[1335197] is descriptor to read in this proces. Now command echo will be works if we will write some to descriptor 3. Using is simply:
$ cd /proc/PID/fd
$ echo 1 > 3
Then we also can using this in select() function but descriptor number is 3 so define should be looks like .
#define STDIN 3
And works
You have wrong assumption that writing to the /proc/pidof application/fd/0 will put data to the stdin stream of the application.
Just read answers to this question: Sending command to java -jar using stdin via /proc/{pid}/fd/0

Perform an action every day after Sep 5

I need to perform an action every day after September 5. I wrote this program
#include <windows.h>
int main()
{
SYSTEMTIME time;
GetLocalTime(&time);
if((time.wMonth = 9 && time.wDay >= 6) || time.wMonth > 9)
{
//perform action
MessageBox(GetForegroundWindow(), "Action performed. Month is " + std::to_string((long long)wMonth), "Alarm!", MB_OK | MB_SYSTEMMODAL);
}
}
I ran this program and the message box displays. But today is August 22, I checked my computer's clock. What am I doing wrong?
Reference SYSTEMTIME
Update:
After writing this question I checked the values of wMonth and wDay and these are 1 and 22, i.e. Jan 22.
Seems like a bug. What do I do to get correct month?
if((time.wMonth = 9 ... needs to be :
if((time.wMonth == 9 ...
^^^^
If you reverse your test (and many C++ programmers do), the compiler will emit an error :
if((9 = time.wMonth ... // error !
Which is a way of catching this frequent typo.
I think is better to use the cron manager (Linux) or Task Manager (Windows) to schedule your job

Second setuid not permitted

If I call setuid in a loop to become root and reset the uid, this works only once.
I have the following code:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int my_func(int i) {
int current_uid = getuid();
int ret;
fprintf(stderr,
"### i=%d ###: My UID is: %d. My GID is: %d, before 'system(id)'\n",
i, current_uid, getgid());
system("/usr/bin/id");
fprintf(stderr,"\n\n### i=%d ###: before 'setuid(0)'\n", i);
if (setuid(0)) {
perror("setuid");
return 1;
}
fprintf(stderr,"after 'setuid(0)'\n\n");
//I am now root!
fprintf(stderr,
"### i=%d ###: I an now root: My UID is: %d. My GID is: %d, before 'system(id)'\n",
i, getuid(), getgid());
system("/usr/bin/id");
//Time to drop back to regular user priviledges
fprintf(stderr,"\n\nbefore 'setuid(%d)'\n",current_uid);
ret=setuid(current_uid);
fprintf(stderr,
"### i=%d ###: My UID is: %d. My GID is: %d, before 'system(id)\n",
i, getuid(), getgid());
system("/usr/bin/id");
}
int main(void) {
int i;
for (i=0;i<3;i++) {
my_func(i);
sleep(5);
fprintf(stderr,"\n\n");
}
return 0;
}
I set the SUID bit and run this program as ordinary user rose. The output is:
rose#condor:/home/rose/Txt/src/Test/C/Setuid(5)$ ll /usr/local/bin/multiple_setuid_test
-rws--x--x 1 root root 13589 11. Dez 08:41 /usr/local/bin/multiple_setuid_test*
rose#condor:/home/rose/Txt/src/Test/C/Setuid(6)$ /usr/local/bin/multiple_setuid_test
i=0 ###: My UID is: 1203. My GID is: 100, before 'system(id)'
uid=1203(rose) gid=100(users) Gruppen=100(users),4(adm),6(disk),7(lp),10(wheel),14(uucp),18(audio),19(cdrom),27(video),35(games),60(mysql),250(portage),1001(haldaemon),1002(plugdev),1008(scanner),1027(vboxusers),1028(kvm),1029(qemu),1036(gsm),1039(pulse-access),1040(pulse),1041(tuntap)
i=0 ###: before 'setuid(0)'
after 'setuid(0)'
i=0 ###: I an now root: My UID is: 0. My GID is: 100, before 'system(id)'
uid=0(root) gid=100(users) Gruppen=0(root),4(adm),6(disk),7(lp),10(wheel),14(uucp),18(audio),19(cdrom),27(video),35(games),60(mysql),100(users),250(portage),1001(haldaemon),1002(plugdev),1008(scanner),1027(vboxusers),1028(kvm),1029(qemu),1036(gsm),1039(pulse-access),1040(pulse),1041(tuntap)
before 'setuid(1203)'
i=0 ###: My UID is: 1203. My GID is: 100, before 'system(id)
uid=1203(rose) gid=100(users) Gruppen=100(users),4(adm),6(disk),7(lp),10(wheel),14(uucp),18(audio),19(cdrom),27(video),35(games),60(mysql),250(portage),1001(haldaemon),1002(plugdev),1008(scanner),1027(vboxusers),1028(kvm),1029(qemu),1036(gsm),1039(pulse-access),1040(pulse),1041(tuntap)
i=1 ###: My UID is: 1203. My GID is: 100, before 'system(id)'
uid=1203(rose) gid=100(users) Gruppen=100(users),4(adm),6(disk),7(lp),10(wheel),14(uucp),18(audio),19(cdrom),27(video),35(games),60(mysql),250(portage),1001(haldaemon),1002(plugdev),1008(scanner),1027(vboxusers),1028(kvm),1029(qemu),1036(gsm),1039(pulse-access),1040(pulse),1041(tuntap)
i=1 ###: before 'setuid(0)'
setuid: Operation not permitted
i=2 ###: My UID is: 1203. My GID is: 100, before 'system(id)'
uid=1203(rose) gid=100(users) Gruppen=100(users),4(adm),6(disk),7(lp),10(wheel),14(uucp),18(audio),19(cdrom),27(video),35(games),60(mysql),250(portage),1001(haldaemon),1002(plugdev),1008(scanner),1027(vboxusers),1028(kvm),1029(qemu),1036(gsm),1039(pulse-access),1040(pulse),1041(tuntap)
i=2 ###: before 'setuid(0)'
setuid: Operation not permitted
rose#condor:/home/rose/Txt/src/Test/C/Setuid(7)$ uname -a
Linux condor 3.12.4 #1 SMP Mon Dec 9 11:37:38 CET 2013 x86_64 Intel(R) Core(TM)2 CPU 6600 # 2.40GHz GenuineIntel GNU/Linux
Any hint is appreciated.
Linux (just like other unixes) store two values: your real user id, which is set by setuid, corresponds to your login, and is not changed by the s-bit, and your effective user id, which is set by seteuid, and gets changed when you execute a program that has the s-bit set. To be allowed to use setuid(), either your real or your effective user id need to be zero, but if you use setuid() to drop privileges (change from 0 to anything else), your effective user id will be changed as well. So your first setuid(1203) sets the effective user id to 1203 as well, which prevents you from regaining privileges later.
To change from and to root several times, you have to use the setreuid() call to swap both - setreuid(1203, 0) would change your real user id to 1203, and the effective user id to 0, thus allowing you to set the uid to 0 later.
Note that, as long as either of the two uids is 0, you have root privileges. With uid=1203 and euid=0, files you create will belong to you (user id 1203), but you'll still have root access. So check your program for security implications very carefully.
If you need to have root access every now and then throughout your program, it's much safer to create a pipe(), fork() off a child process that keeps root privileges, drop privileges in the parent process, and send some command down the pipe for the child to execute when you need something done as root. That way, you have to security audit only the child process, which is presumably much smaller than your whole program.
Once you give up root privileges by using setuid to change to a non-root user, you no longer have the privileges necessary to use setuid to become root once again.