consider the following case:
an EPOLLIN event is registered for fd 0 (stdin)
an EPOLLIN event is generated for fd 0 and implicitly queued for read within epoll
fd 0 is closed (and EPOLL_CTL_DELeted) before calling epoll_wait()
epoll_wait() is called to read the queued events
Now:
if stdin is a terminal, when epoll_wait() is called, the EPOLLIN event from step 2 will be reported
if stdin is not a terminal but a pipe, the EPOLLIN event from step 2 will not be reported
Why is the tty case different?
The test program:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/epoll.h>
struct epoll_event event1 = {
.events = EPOLLIN,
.data = { .fd = 0}
};
int main(int argc, char **argv)
{
int epfd = epoll_create(1);
int rc;
epoll_ctl(epfd, EPOLL_CTL_ADD, 0, &event1);
sleep(2); //allow meself time to type false\n
printf("closing stdin ...\n");
close(0);
//even if i remove it explicitly the event will be found in the que after
epoll_ctl(epfd, EPOLL_CTL_DEL, 0, &event1);
printf("gathering events ...\n");
event1.events = 0;
event1.data.fd = -1;
rc = epoll_wait(epfd, &event1, 1, 0);
switch(rc) {
case 1:
printf("event received: event=%d on fd %d\n", event1.events, event1.data.fd);
break;
case 0:
printf("no events received");
break;
case -1:
printf("epoll_wait error\n");
break;
default:
printf("weird event count %d\n", rc);
}
return 0;
}
running the program with stdin from tty:
[root#tinkerbell src]# ./epolltest
false
closing stdin ...
gathering events ...
event received: event=1 on fd 0
[root#tinkerbell src]# false
[root#tinkerbell src]#
running the program with stdin from a pipe:
[root#tinkerbell src]# cat t.sh
#!/bin/bash
echo "bah";
sleep 10;
[root#tinkerbell src]# ./t.sh | ./epolltest
closing stdin ...
gathering events ...
no events received[root#tinkerbell src]#
different question but the answer can be applied here as well
Events caught by epoll comes from a file* since that is the
abstraction the kernel handles. Events really happen on the file* and
there's no way if you dup()ing 1000 times a single fd, to say that
events are for fd = 122.
Related
I'm required to replace some obsolete RPC calls in the base code. I have to replace "svcfd_create()" with "svc_fd_create()". The changes were working successfully on linux, however it is failing on SOLARIS.
I created the following sample program to check the scenario, "svcfd_create()" is working successfully however "svc_fd_create()" fails with the error "socket: Bad file number".
Platfrom:
bash-3.2# uname -a
SunOS XXXXXXX 5.10 Generic_Virtual sun4v sparc sun4v
Command used to compile:
/usr/bin/CC -R/usr/ucblib -L/usr/ucblib -L/usr/lib -lsocket -lrpcsoc -lnsl Server.c
#include <stdio.h>
#include <stdlib.h>
#include <rpc/rpc.h>
#include <rpc/svc_soc.h>
#include <errno.h>
#include <string.h>
#include <memory.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
main()
{
register SVCXPRT *transp;
struct sockaddr_in serv_addr;
memset(&serv_addr,0,sizeof(serv_addr));
int sock;
int pid;
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) printf("ERROR opening socket");
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(2363);
if (bind(sock, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
printf("ERROR on binding \n");
listen(sock,5);
perror("socket");
printf("Socket created : %d \n", sock);
printf("before svc_fd_create \n");
// Uncomment the line with "svcfd_create" and comment the line with "svc_fd_create" to run success scenario
//transp = svcfd_create(sock, 0, 0); // RPC CALL WORKING
transp = svc_fd_create(sock, 0, 0); // RPC CALL NOT WORKING
printf("after svc_fd_create \n");
perror("socket");
if (transp == NULL) {
printf ("cannot create tcp service.\n");
fprintf(stderr, "socket() failed: %s\n", strerror(errno));
exit(1);
}
else
{
printf ("transp->xp_fd: %d \n", transp->xp_fd);
}
}
With "svcfd_create", it results in following output:
bash-3.2# ./a.out
socket: Error 0
Socket created : 3
before svc_fd_create
after svc_fd_create
socket: Error 0
transp->xp_fd: 3
With "svc_fd_create", it results in following output:
bash-3.2# ./a.out
socket: Error 0
Socket created : 3
before svc_fd_create
after svc_fd_create
socket: Bad file number
cannot create tcp service.
socket() failed: Bad file number
What is missing here to make "svc_fd_create()" work successfully. I'm at a loss here.
I'm writing an app that (ab)uses an APL engine, libapl.so. The library contains a mechanism to allow me to capture results, but some stuff it dumps to stdout and stderr. So my question is, is there way a to capture stuff written to stdout rather than having it go to a screen, get piped to another process, or some such? Is there a way, for example, to connect stdout to stdin of the same process? I've tinkered with pipe2(), dup(2), and various bits of weirdness in GTK+/Glib, but I haven't hit the right incantation yet.
Did some more poking--at least one solution seems to be to create a fifo, open() it twice, once for reading, one for writing, and dup2() the writing fd to the stdout fd. This results in writes to stdout going through the fifo pipe where it can be read by the application. (Thanks for some inspiration by someone named Hasturkun, almost 7 years ago.)
Here's a bit of demo code:
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
int
main (int ac, char *av[])
{
char tname[64];
sprintf (tname, "/tmp/testpipe%d", (int)getpid ());
int rc = mkfifo (tname, 0666);
if (rc != 0) {
perror ("Creating fifo");
return 1;
}
int temp_in_fd = open (tname, O_NONBLOCK | O_RDONLY);
if (temp_in_fd < 0) {
perror ("Opening new input");
return 1;
}
int temp_out_fd = open (tname, O_NONBLOCK | O_WRONLY);
if (temp_out_fd < 0) {
perror ("Opening new output");
return 1;
}
FILE *temp_in = fdopen (temp_in_fd, "r");
if (!temp_in) {
perror ("Creating new input FILE");
return 1;
}
FILE *temp_out = fdopen (temp_out_fd, "w");
if (!temp_out) {
perror ("Creating new input FILE");
return 1;
}
dup2 (fileno (temp_out), STDOUT_FILENO);
printf("Woot!");
fflush(stdout);
#define BFR_SIZE 64
char bfr[BFR_SIZE];
ssize_t sz = fread (bfr, 1, BFR_SIZE, temp_in);
fprintf (stderr, "got %d bytes: \"%s\"\n", (int)sz, bfr);
fclose (temp_out);
fclose (temp_in);
unlink (tname);
return 0;
}
i have a problem with the pthread library in a C-Application for Linux.
In my Application a Thread is started over and over again.
But I allways wait until the Thread is finished before starting it.
At some point the thread doesn't start anymore and I get an out of memory error.
The solution I found is to do a pthread_join after the thread has finished.
Can anyone tell me why the Thread doesn't end correctly?
Here is an Example Code, that causes the same Problem.
If the pthread_join isn't called the Process stops at about 380 calls of the Thread:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <pthread.h>
#include <unistd.h>
volatile uint8_t check_p1 = 0;
uint32_t stack_start;
void *thread1(void *ch)
{
static int counter = 0;
int i;
int s[100000];
char stack_end;
srand(time(NULL) + counter);
for (i = 0; i < (sizeof (s)/sizeof(int)); i++) //do something
{
s[i] = rand();
}
counter++;
printf("Thread %i finished. Stacksize: %u\n", counter, ((uint32_t) (stack_start)-(uint32_t) (&stack_end)));
check_p1 = 1; // Mark Thread as finished
return 0;
}
int main(int argc, char *argv[])
{
pthread_t p1;
int counter = 0;
stack_start = (uint32_t)&counter; // save the Address of counter
while (1)
{
counter++;
check_p1 = 0;
printf("Start Thread %i\n", counter);
pthread_create(&p1, NULL, thread1, 0);
while (!check_p1) // wait until thread has finished
{
usleep(100);
}
usleep(1000); // wait a little bit to be really sure that the thread is finished
//pthread_join(p1,0); // crash without pthread_join
}
return 0;
}
The solution I found is to do a pthread_join after the thread has finished.
That is the correct solution. You must do that, or you leak thread resources.
Can anyone tell me why the Thread doesn't end correctly?
It does end correctly, but you must join it in order for the thread library to know: "yes, he is really done with this thread; no need to hold resources any longer".
This is exactly the same reason you must use wait (or waitpid, etc.) in this loop:
while (1) {
int status;
pid_t p = fork();
if (p == 0) exit(0); // child
// parent
wait(&status); // without this wait, you will run out of OS resources.
}
Okay so, i am building a utility to monitor filesystem, registry and network activity (process wise; only activity by selected processes). I have accomplished the filesystem and registry activity part by developing a minifilter driver. However, i am uncertain as to how should i do it for the network. What i want to do is much like what sysinternal's TCPView does, however i only want to monitor ESTABLISHED connections by the selected processes. Here is what i want to get in real time for each connection:
-protocol (TCP or UDP)
-source port
-remote IP and port
-[optional] amount of bytes transferred on a particular connection from the time that the monitoring started
What should i use? i heard about LSPs, but reading into it a bit further i realized that it is VERY difficult to write proper functioning LSPs, not to mention that there is hardly any material available for them to learn from scratch. Also that they are becoming obsolete. Problem is that i only have about 2-3 weeks of time to learn+write this module. Due to the time limit i certainly don't want to go for something like WFP, unless there is a very good tutorial for it out there, and i am not talking about the MSDN documentation. I don't know if this could be 'easily' done using NDIS etc.
Anyhow, so what should i do, where should i focus my efforts. Should i take the risk with learning about the LSPs, or would NDIS accomplish the task, or something else. I am kind of clueless right now. Help me out here!
Look at GetExtendedTcpTable and GetExtendedUdpTable. These APIs will get you most of what you need. But just to keep things interesting, the demo code I wrote uses GetTcp6Table2 instead.
#define WIN32_LEAN_AND_MEAN
#define UNICODE
#define _UNICODE
#include <windows.h>
#include <winsock2.h>
#include <Ws2tcpip.h>
#include <iphlpapi.h>
#include <Tcpestats.h>
#include <Tcpmib.h>
#include <Mstcpip.h>
#include <stdlib.h>
#include <stdio.h>
#pragma comment(lib, "iphlpapi.lib")
#pragma comment(lib, "ws2_32.lib")
PCWSTR
StringFromState(MIB_TCP_STATE State)
{
switch (State)
{
case MIB_TCP_STATE_CLOSED:
return L"CLOSED";
case MIB_TCP_STATE_LISTEN:
return L"LISTEN";
case MIB_TCP_STATE_SYN_SENT:
return L"SYN_SENT";
case MIB_TCP_STATE_SYN_RCVD:
return L"SYN_RCVD";
case MIB_TCP_STATE_ESTAB:
return L"ESTAB";
case MIB_TCP_STATE_FIN_WAIT1:
return L"FIN_WAIT1";
case MIB_TCP_STATE_FIN_WAIT2:
return L"FIN_WAIT2";
case MIB_TCP_STATE_CLOSE_WAIT:
return L"CLOSE_WAIT";
case MIB_TCP_STATE_CLOSING:
return L"CLOSING";
case MIB_TCP_STATE_LAST_ACK:
return L"LAST_ACK";
case MIB_TCP_STATE_TIME_WAIT:
return L"TIME_WAIT";
case MIB_TCP_STATE_DELETE_TCB:
return L"DELETE_TCB";
default:
return L"[Unknown]";
}
}
LPWSTR (NTAPI *pRtlIpv6AddressToStringW)(const IN6_ADDR *, LPWSTR);
int __cdecl main()
{
ULONG r;
// We need to load this dynamically, because ntdll.lib doesn't export it
HMODULE ntdll = LoadLibrary(L"ntdll");
pRtlIpv6AddressToStringW = (decltype(pRtlIpv6AddressToStringW))GetProcAddress(ntdll, "RtlIpv6AddressToStringW");
// Initial guess for the table size
ULONG cbTable = 100;
MIB_TCP6TABLE2 *table = nullptr;
while (true)
{
table = (MIB_TCP6TABLE2*)malloc(cbTable);
if (!table)
return 1;
r = GetTcp6Table2(table, &cbTable, FALSE);
if (ERROR_INSUFFICIENT_BUFFER == r)
{
// Try again with bigger buffer
free(table);
continue;
}
else if (ERROR_SUCCESS == r)
{
break;
}
else
{
free(table);
wprintf(L"GetTcp6Table2 = %u\n", r);
return 1;
}
}
// Print table heading
wprintf(L"%56s %56s %10s %6s\n", L"Local endpoint", L"Remote endpoint", L"State", L"PID");
for (ULONG i = 0; i < table->dwNumEntries; i++)
{
MIB_TCP6ROW2 const &entry = table->table[i];
WCHAR localAddr[46];
WCHAR remoteAddr[46];
pRtlIpv6AddressToStringW(&entry.LocalAddr, localAddr);
pRtlIpv6AddressToStringW(&entry.RemoteAddr, remoteAddr);
WCHAR localEndpoint[56];
WCHAR remoteEndpoint[56];
swprintf_s(localEndpoint, L"[%s]:%-5u", localAddr, ntohs(entry.dwLocalPort));
swprintf_s(remoteEndpoint, L"[%s]:%-5u", remoteAddr, ntohs(entry.dwRemotePort));
wprintf(L"%56s %56s %10s %6u\n",
localEndpoint, remoteEndpoint,
StringFromState(entry.State),
entry.dwOwningPid);
}
free(table);
return 0;
}
Example output (actual addresses anonymized):
C:\>test.exe
Local endpoint Remote endpoint State PID
[::]:80 [::]:0 LISTEN 4
[::]:135 [::]:0 LISTEN 980
[::]:445 [::]:0 LISTEN 4
[::]:1025 [::]:0 LISTEN 692
[2001:xxxx:x:xxx:x:xxxx:xxx.xx.xxx.xx]:6044 [xxxx:xxx:xxxx:xxxx::x]:443 ESTAB 3248
[2001:xxxx:x:xxx:x:xxxx:xxx.xx.xxx.xx]:6045 [xxxx:xxx:xxxx:xxxx::x]:443 ESTAB 3248
[2001:xxxx:xx:x:xxxx:xxxx:xxxx:xxxx]:53759 [2001:xxxx:xx:xxxx:xxx:xxxx:xxxx:xxxx]:135 TIME_WAIT 0
Sounds to me like you want something like winpcap which is what wireshark uses.
http://www.winpcap.org/
Also the netstat code from ReactOS might be interesting
http://doxygen.reactos.org/dd/d3f/netstat_8c_source.html
I've been creating programs exemplifying concurrency bugs using POSIX threads.
The overall question I have is what is the difference between the main() thread and one created by pthread_create(). My original understanding was that they are pretty much the same but, I'm getting different results from the two programs below.
To expand before showing the code I've written, what I am wondering is: Is there a difference between the following.
int main() {
...
pthread_create(&t1, NULL, worker, NULL);
pthread_create(&t2, NULL, worker, NULL);
...
}
and
int main() {
...
pthread_create(&t1, NULL, worker, NULL);
worker();
...
}
To expand using a full example program. I've made two versions of the same program. They both have the same function worker()
void *worker(void *arg) {
printf("Entered worker function\n");
int myid;
int data = 999;
pthread_mutex_lock(&gidLock);
myid = gid;
gid++;
printf("myid == %d\n", myid);
pthread_mutex_unlock(&gidLock);
if (myid == 0) {
printf("Sleeping since myid == 0\n");
sleep(1);
result = data;
printf("Result updated\n");
}
return NULL;
}
gid and data are globals initialized to 0.
What's the difference between the following main() functions
int main_1() {
pthread_t t1, t2;
int tmp;
/* initialize globals */
gid = 0;
result = 0;
pthread_create(&t1, NULL, worker, NULL);
pthread_create(&t2, NULL, worker, NULL);
pthread_join(t2, NULL);
printf("Parent thread exited worker function\n");
tmp = result;
printf("%d\n", tmp);
pthread_exit((void *) 0);
}
and
int main_2() {
pthread_t t1;
int tmp;
/* initialize globals */
gid = 0;
result = 0;
pthread_create(&t1, NULL, worker, NULL);
worker(NULL);
printf("Parent thread exited worker function\n");
tmp = result;
printf("%d\n", tmp);
pthread_exit((void *) 0);
}
Sample output for main_1()
Entered worker function
myid == 0
Sleeping since myid == 0
Entered worker function
myid == 1
Parent thread exited worker function
0
Result Updated
Sample output for main_2()
Entered worker function
myid == 0
Sleeping since myid == 0
Entered worker function
myid == 1
/* program waits here */
Result updated
Parent thread exited worker function
999
Edit: The program intentionally has a concurrency bug (an atomicity violation). Delays were added by calling sleep() to attempt to force the buggy interleaving to occur. The intention of the program is to be used to test software automatically detecting concurrency bugs.
I would think that main_1() and main_2() are essentially the same program which should result in the same interleaving when run on the same system (or largely the same interleaving; it is indeterminate, but running the same program on the same system only tend explores a small section of the potential scheduling and rarely deviates [1]).
The "desired" output is is that from main_1()
I'm not sure why the thread with myid == 1 stalls and does not return in main_2(). If I had to guess
Thanks for reading this far, and if anyone needs more information I'd be happy to oblige. Here are links to the full source code.
main_1(): https://gist.github.com/2942372
main_2(): https://gist.github.com/2942375
I've been compiling with gcc -pthread -lpthread
Thanks again.
[1] S. Park, S. Lu, Y. Zhou. "CTrigger: Exposing Atomicity Violation Bugs from Their Hiding Places"