ObjFW  Check-in [846125bed6]

Overview
Comment:Fix async connect with epoll
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 846125bed62e420787761ab0af462a4b4d64dbc83e6fee3e890baabdceab03aa
User & Date: js on 2019-09-07 23:28:50
Other Links: manifest | tags
Context
2019-09-07
23:33
ofhttp: Fix error code not always being set check-in: 9764b0886f user: js tags: trunk
23:28
Fix async connect with epoll check-in: 846125bed6 user: js tags: trunk
2019-09-01
18:50
condition.h: Remove OF_ASSUME_NONNULL_{BEGIN,END} check-in: 35b6a34c32 user: js tags: trunk
Changes

Modified src/OFEpollKernelEventObserver.m from [5cdf80c1e6] to [06e819f56f].

126
127
128
129
130
131
132






133
134
135
136
137
138
139
140
141
142

	events = (intptr_t)[_FDToEvents
	    objectForKey: (void *)((intptr_t)fd + 1)];
	events &= ~removeEvents;

	if (events == 0) {
		if (epoll_ctl(_epfd, EPOLL_CTL_DEL, fd, NULL) == -1)






			@throw [OFObserveFailedException
			    exceptionWithObserver: self
					    errNo: errno];

		[_FDToEvents removeObjectForKey: (void *)((intptr_t)fd + 1)];
	} else {
		struct epoll_event event;

		memset(&event, 0, sizeof(event));
		event.events = (int)events;







>
>
>
>
>
>
|
|
|







126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148

	events = (intptr_t)[_FDToEvents
	    objectForKey: (void *)((intptr_t)fd + 1)];
	events &= ~removeEvents;

	if (events == 0) {
		if (epoll_ctl(_epfd, EPOLL_CTL_DEL, fd, NULL) == -1)
			/*
			 * When an async connect fails, it seems the socket is
			 * automatically removed from epoll, meaning ENOENT is
			 * returned when we try to remove it after it failed.
			 */
			if (errno != ENOENT)
				@throw [OFObserveFailedException
				    exceptionWithObserver: self
						    errNo: errno];

		[_FDToEvents removeObjectForKey: (void *)((intptr_t)fd + 1)];
	} else {
		struct epoll_event event;

		memset(&event, 0, sizeof(event));
		event.events = (int)events;

Modified src/OFRunLoop.m from [747027d6fd] to [d7aa5cb83d].

700
701
702
703
704
705
706
707












708
709







710
711
712
713
714
715
716
		exception = [OFConnectionFailedException
		    exceptionWithHost: nil
				 port: 0
			       socket: object
				errNo: errNo];

	if ([_delegate respondsToSelector:
	    @selector(of_socketDidConnect:exception:)])












		[_delegate of_socketDidConnect: object
				     exception: exception];








	return false;
}
@end
# endif

@implementation OFRunLoopAcceptQueueItem







|
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>
>
>
>







700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
		exception = [OFConnectionFailedException
		    exceptionWithHost: nil
				 port: 0
			       socket: object
				errNo: errNo];

	if ([_delegate respondsToSelector:
	    @selector(of_socketDidConnect:exception:)]) {
		/*
		 * Make sure we only call the delegate once we removed the
		 * socket from the kernel event observer. This is necessary as
		 * otherwise we could try to connect to the next address and it
		 * would not be re-registered with the kernel event observer,
		 * which is necessary for some kernel event observers (e.g.
		 * epoll) even if the fd of the new socket is the same.
		 */
		OFRunLoop *runLoop = [OFRunLoop currentRunLoop];
		OFTimer *timer = [OFTimer
		    timerWithTimeInterval: 0
				   target: _delegate
				 selector: @selector(of_socketDidConnect:
					       exception:)
				   object: object
				   object: exception
				  repeats: false];

		[runLoop addTimer: timer
			  forMode: runLoop.currentMode];
	}

	return false;
}
@end
# endif

@implementation OFRunLoopAcceptQueueItem